Looks like an issue in the collision manager. The bounding box intersection test is using a poorly constructed bounding box when doing the ray-box intersection test. The following code will demonstrate...
Code: Select all
#include <irrlicht.h>
#pragma comment(lib, "Irrlicht.lib")
using namespace irr;
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(scene::ISceneManager* smgr)
: SceneManager(smgr)
, ShiftKeyDown(false)
, SelectedNode(0)
{
SceneManager->grab();
}
virtual ~MyEventReceiver()
{
SceneManager->drop();
}
// you may need to change the parameter type depending on your Irrlicht version
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == EET_KEY_INPUT_EVENT &&
event.KeyInput.Key == KEY_SHIFT)
{
ShiftKeyDown = event.KeyInput.PressedDown;
return true;
}
// if shift is down and mouse clicked, then do collision test
if (ShiftKeyDown &&
event.EventType == EET_MOUSE_INPUT_EVENT &&
event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
{
const core::position2di pos(event.MouseInput.X, event.MouseInput.Y);
SelectedNode =
SceneManager->getSceneCollisionManager()->getSceneNodeFromScreenCoordinatesBB(pos);
return true;
}
return false;
}
private:
scene::ISceneManager* SceneManager;
bool ShiftKeyDown;
public:
scene::ISceneNode* SelectedNode;
};
// draw the world aligned bounding box that completely encloses the object bounding box
void ISceneNode_drawWorldBoundingBox(scene::ISceneNode* node,
video::IVideoDriver* driver,
video::SColor color = video::SColor(255, 255, 0, 0))
{
if (!node || !driver)
return;
video::SMaterial matl;
matl.Lighting = false;
driver->setMaterial(matl);
core::matrix4 matx;
driver->setTransform(video::ETS_WORLD, matx);
core::aabbox3df bbox(node->getBoundingBox());
node->getAbsoluteTransformation().transformBoxEx(bbox);
driver->draw3DBox(bbox, color);
}
// draw the object aligned bounding box
void ISceneNode_drawObjectBoundingBox(scene::ISceneNode* node,
video::IVideoDriver* driver,
video::SColor color = video::SColor(255, 0, 255, 0))
{
if (!node || !driver)
return;
video::SMaterial matl;
matl.Lighting = false;
driver->setMaterial(matl);
driver->setTransform(video::ETS_WORLD, node->getAbsoluteTransformation());
driver->draw3DBox(node->getBoundingBox(), color);
}
// draw the transformed object bounding box
void ISceneNode_drawTransformedBoundingBox(scene::ISceneNode* node,
video::IVideoDriver* driver,
video::SColor color = video::SColor(255, 0, 0, 255))
{
if (!node || !driver)
return;
video::SMaterial matl;
matl.Lighting = false;
driver->setMaterial(matl);
core::matrix4 matx;
driver->setTransform(video::ETS_WORLD, matx);
driver->draw3DBox(node->getTransformedBoundingBox(), color);
}
int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType =
video::EDT_DIRECT3D9;
// create device and exit if creation failed
IrrlichtDevice *device = createDevice(driverType, core::dimension2d<s32>(800, 600), 32, false, false, true);
if (device == 0)
return 1; // could not create selected driver.
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
MyEventReceiver receiver(smgr);
device->setEventReceiver(&receiver);
// add camera
smgr->addCameraSceneNodeMaya();
// load pre-built scene. you may want to remove the animators so things stay still
smgr->loadScene("media/example.irr");
s32 fps = 0;
while(device->run())
{
// window is active, so render scene
if (device->isWindowActive())
{
if (driver->beginScene(true, true, video::SColor(100, 50, 50, 100)))
{
smgr->drawAll();
ISceneNode_drawWorldBoundingBox(receiver.SelectedNode, driver);
ISceneNode_drawObjectBoundingBox(receiver.SelectedNode, driver);
ISceneNode_drawTransformedBoundingBox(receiver.SelectedNode, driver);
driver->endScene();
}
}
}
device->drop();
return 0;
}
The code uses the maya camera scene node controls, and if you press Shift+Click, you will select a node. Several bounding boxes are drawn for the selected node.
You will notice that the node selection works if you click in the area that is enclosed by the blue bounding box. Most users would expect that the green bounding box would be used for the bounding box tests, or maybe even the red box.
The issue is in the scene collision manager. It uses the nodes
getTransformedBoundingBox() method to get the the bounding box for collision testing. For accurate collision testing, the ray should be transformed into object space [using the inverse of the object absolute transform] and then tested against the object space bounding box.
Travis