Change from dimension2d<s32> to dimension2d<u32> where practical. IImage and ITexture now have unsigned dimensions, as does screen size. This has had a significant knock-on through the code base, but it is more technically correct - the BEST KIND of correct. GUI elements and draw2DImage methods still have and take signed dimensions, but we can look into this in future. Regression tested with the test suite and the example apps. Note that createDevice() now takes dimension2d<u32>! git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2092 dfc29bdd-3216-0410-991c-e03cc46cb475
285 lines
8.5 KiB
C++
285 lines
8.5 KiB
C++
// Copyright (C) 2008-2009 Colin MacDonald
|
|
// No rights reserved: this software is in the public domain.
|
|
|
|
#include "testUtils.h"
|
|
#include "irrlicht.h"
|
|
#include <assert.h>
|
|
|
|
using namespace irr;
|
|
using namespace core;
|
|
using namespace scene;
|
|
using namespace video;
|
|
|
|
static bool testGetCollisionResultPosition(IrrlichtDevice * device,
|
|
ISceneManager * smgr,
|
|
ISceneCollisionManager * collMgr)
|
|
{
|
|
IMeshSceneNode * cubeNode = smgr->addCubeSceneNode(10.f);
|
|
ITriangleSelector * cubeSelector = smgr->createTriangleSelectorFromBoundingBox(cubeNode);
|
|
|
|
triangle3df triOut;
|
|
vector3df hitPosition;
|
|
bool falling;
|
|
|
|
vector3df resultPosition =
|
|
collMgr->getCollisionResultPosition(cubeSelector,
|
|
vector3df(0, 50, 0),
|
|
vector3df(10, 20, 10),
|
|
vector3df(0, -100, 0),
|
|
triOut,
|
|
hitPosition,
|
|
falling);
|
|
|
|
bool result = true;
|
|
if(!equals(resultPosition.Y, 25.f, 0.01f))
|
|
{
|
|
logTestString("Unexpected collision response position\n");
|
|
assert(false);
|
|
result = false;
|
|
}
|
|
|
|
if(!equals(hitPosition.Y, 5.f, 0.01f))
|
|
{
|
|
logTestString("Unexpected collision position\n");
|
|
assert(false);
|
|
result = false;
|
|
}
|
|
|
|
resultPosition =
|
|
collMgr->getCollisionResultPosition(cubeSelector,
|
|
vector3df(-20, 0, 0),
|
|
vector3df(10, 20, 10),
|
|
vector3df(100, 0, 0),
|
|
triOut,
|
|
hitPosition,
|
|
falling);
|
|
|
|
if(!equals(resultPosition.X, -15.f, 0.01f))
|
|
{
|
|
logTestString("Unexpected collision response position\n");
|
|
assert(false);
|
|
result = false;
|
|
}
|
|
|
|
if(!equals(hitPosition.X, -5.f, 0.01f))
|
|
{
|
|
logTestString("Unexpected collision position\n");
|
|
assert(false);
|
|
result = false;
|
|
}
|
|
|
|
cubeSelector->drop();
|
|
smgr->clear();
|
|
return result;
|
|
}
|
|
|
|
|
|
// Test that getCollisionPoint() actually uses the closest point, not the closest triangle.
|
|
static bool getCollisionPoint_ignoreTriangleVertices(IrrlichtDevice * device,
|
|
ISceneManager * smgr,
|
|
ISceneCollisionManager * collMgr)
|
|
{
|
|
// Create a cube with a Z face at 5, but corners close to 0
|
|
ISceneNode * farSmallCube = smgr->addCubeSceneNode(10, 0, -1, vector3df(0, 0, 10));
|
|
|
|
// Create a cube with a Z face at 0, but corners far from 0
|
|
ISceneNode * nearBigCube = smgr->addCubeSceneNode(100, 0, -1, vector3df(0, 0, 50));
|
|
|
|
IMetaTriangleSelector * meta = smgr->createMetaTriangleSelector();
|
|
|
|
ITriangleSelector * selector = smgr->createTriangleSelectorFromBoundingBox(farSmallCube);
|
|
meta->addTriangleSelector(selector);
|
|
selector->drop();
|
|
|
|
// We should expect a hit on this cube
|
|
selector = smgr->createTriangleSelectorFromBoundingBox(nearBigCube);
|
|
meta->addTriangleSelector(selector);
|
|
selector->drop();
|
|
|
|
line3df ray(0, 0, -5, 0, 0, 100);
|
|
vector3df hitPosition;
|
|
triangle3df hitTriangle;
|
|
|
|
bool collision = collMgr->getCollisionPoint(ray, meta, hitPosition, hitTriangle);
|
|
|
|
meta->drop();
|
|
|
|
if(!collision)
|
|
{
|
|
logTestString("getCollisionPoint_ignoreTriangleVertices: didn't get a hit.\n");
|
|
return false;
|
|
}
|
|
|
|
if(hitPosition != vector3df(0, 0, 0))
|
|
{
|
|
logTestString("getCollisionPoint_ignoreTriangleVertices: unexpected hit position %f %f %f.\n",
|
|
hitPosition.X, hitPosition.Y, hitPosition.Z );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool testGetSceneNodeFromScreenCoordinatesBB(IrrlichtDevice * device,
|
|
ISceneManager * smgr,
|
|
ISceneCollisionManager * collMgr)
|
|
{
|
|
// Create 3 nodes. The nearest node actually contains the camera.
|
|
IMeshSceneNode * cubeNode1 = smgr->addCubeSceneNode(10.f, 0, -1, vector3df(0, 0, 4));
|
|
IMeshSceneNode * cubeNode2 = smgr->addCubeSceneNode(10.f, 0, -1, vector3df(0, 0, 30));
|
|
cubeNode2->setRotation(vector3df(90.f, 90.f, 90.f)); // Just check that rotation doesn't stop us hitting it.
|
|
IMeshSceneNode * cubeNode3 = smgr->addCubeSceneNode(10.f, 0, -1, vector3df(0, 0, 40));
|
|
cubeNode3->setRotation(vector3df(180.f, 180.f, 180.f)); // Just check that rotation doesn't stop us hitting it.
|
|
|
|
ICameraSceneNode * camera = smgr->addCameraSceneNode();
|
|
device->run();
|
|
smgr->drawAll(); // Get the camera in a good state
|
|
|
|
ISceneNode * hitNode = collMgr->getSceneNodeFromScreenCoordinatesBB(position2d<s32>(80, 60));
|
|
|
|
// Expect the first node to be hit, since we're starting the check from inside it.
|
|
bool result = true;
|
|
if(hitNode != cubeNode1)
|
|
{
|
|
logTestString("Unexpected node hit. Expected cubeNode1.\n");
|
|
result = false;
|
|
}
|
|
|
|
// Now make cubeNode1 invisible and check that cubeNode2 is hit.
|
|
cubeNode1->setVisible(false);
|
|
hitNode = collMgr->getSceneNodeFromScreenCoordinatesBB(position2d<s32>(80, 60));
|
|
if(hitNode != cubeNode2)
|
|
{
|
|
logTestString("Unexpected node hit. Expected cubeNode2.\n");
|
|
result = false;
|
|
}
|
|
|
|
// Make cubeNode1 the parent of cubeNode2.
|
|
cubeNode2->setParent(cubeNode1);
|
|
|
|
// Check visibility.
|
|
bool visible = cubeNode2->isVisible();
|
|
if(!visible)
|
|
{
|
|
logTestString("cubeNode2 should think that it (in isolation) is visible.\n");
|
|
result = false;
|
|
}
|
|
|
|
visible = cubeNode2->isTrulyVisible();
|
|
if(visible)
|
|
{
|
|
logTestString("cubeNode2 should know that it (recursively) is invisible.\n");
|
|
result = false;
|
|
}
|
|
|
|
// cubeNode2 should now be an invalid target as well, and so the final cube node should be hit.
|
|
hitNode = collMgr->getSceneNodeFromScreenCoordinatesBB(position2d<s32>(80, 60));
|
|
if(hitNode != cubeNode3)
|
|
{
|
|
logTestString("Unexpected node hit. Expected cubeNode3.\n");
|
|
result = false;
|
|
}
|
|
|
|
|
|
// Make cubeNode3 invisible and check that the camera node is hit (since it has a valid bounding box).
|
|
cubeNode3->setVisible(false);
|
|
hitNode = collMgr->getSceneNodeFromScreenCoordinatesBB(position2d<s32>(80, 60));
|
|
if(hitNode != camera)
|
|
{
|
|
logTestString("Unexpected node hit. Expected the camera node.\n");
|
|
result = false;
|
|
}
|
|
|
|
// Now verify bitmasking
|
|
camera->setID(0xAAAAAAAA); // == 101010101010101010101010101010
|
|
hitNode = collMgr->getSceneNodeFromScreenCoordinatesBB(position2d<s32>(80, 60), 0x02);
|
|
if(hitNode != camera)
|
|
{
|
|
logTestString("Unexpected node hit. Expected the camera node.\n");
|
|
result = false;
|
|
}
|
|
|
|
// Test the 01010101010101010101010101010101 bitmask (0x55555555)
|
|
hitNode = collMgr->getSceneNodeFromScreenCoordinatesBB(position2d<s32>(80, 60), 0x55555555);
|
|
if(hitNode != 0)
|
|
{
|
|
logTestString("A node was hit when none was expected.\n");
|
|
result = false;
|
|
}
|
|
|
|
smgr->clear();
|
|
|
|
if(!result)
|
|
assert(false);
|
|
return result;
|
|
}
|
|
|
|
|
|
static bool getScaledPickedNodeBB(IrrlichtDevice * device,
|
|
ISceneManager * smgr,
|
|
ISceneCollisionManager * collMgr)
|
|
{
|
|
ISceneNode* farTarget = smgr->addCubeSceneNode(1.f);
|
|
farTarget->setScale(vector3df(100.f, 100.f, 10.f));
|
|
farTarget->setPosition(vector3df(0.f, 0.f, 500.f));
|
|
farTarget->updateAbsolutePosition();
|
|
|
|
// Create a node that's slightly further away than the closest node,
|
|
// but thinner. Its furthest corner is closer, but the collision
|
|
// position is further, so it should not be selected.
|
|
ISceneNode* middleTarget = smgr->addCubeSceneNode(10.f);
|
|
middleTarget->setPosition(vector3df(0.f, 0.f, 101.f));
|
|
middleTarget->setScale(vector3df(1.f, 1.f, 0.5f));
|
|
middleTarget->updateAbsolutePosition();
|
|
|
|
ISceneNode* nearTarget = smgr->addCubeSceneNode(10.f);
|
|
nearTarget->setPosition(vector3df(0.f, 0.f, 100.f));
|
|
nearTarget->updateAbsolutePosition();
|
|
// We'll rotate this node 90 degrees to show that we can hit its side.
|
|
nearTarget->setRotation(vector3df(0.f, 90.f, 0.f));
|
|
|
|
line3df ray(0.f, 0.f, 0.f, 0.f, 0.f, 500.f);
|
|
|
|
const ISceneNode * const hit = collMgr->getSceneNodeFromRayBB(ray);
|
|
|
|
bool result = (hit == nearTarget);
|
|
|
|
if(hit == 0)
|
|
logTestString("getSceneNodeFromRayBB() didn't hit anything.\n");
|
|
else if(hit == farTarget)
|
|
logTestString("getSceneNodeFromRayBB() hit the far (scaled) target.\n");
|
|
else if(hit == middleTarget)
|
|
logTestString("getSceneNodeFromRayBB() hit the far (scaled) target.\n");
|
|
|
|
if(!result)
|
|
assert(false);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/** Test functionality of the sceneCollisionManager */
|
|
bool sceneCollisionManager(void)
|
|
{
|
|
IrrlichtDevice * device = irr::createDevice(video::EDT_NULL, dimension2d<u32>(160, 120));
|
|
assert(device);
|
|
if(!device)
|
|
return false;
|
|
|
|
ISceneManager * smgr = device->getSceneManager();
|
|
ISceneCollisionManager * collMgr = smgr->getSceneCollisionManager();
|
|
|
|
bool result = testGetCollisionResultPosition(device, smgr, collMgr);
|
|
|
|
result &= testGetSceneNodeFromScreenCoordinatesBB(device, smgr, collMgr);
|
|
|
|
result &= getScaledPickedNodeBB(device, smgr, collMgr);
|
|
|
|
result &= getCollisionPoint_ignoreTriangleVertices(device, smgr, collMgr);
|
|
|
|
device->drop();
|
|
return result;
|
|
}
|
|
|