This is not a multithreading problem. The frustum culling code is taking an easy-out and checking against the node bounding box that is incorrectly transformed into world space. When the parent node, or any node for that matter, has a rotation applied, the bounding boxes are wrong.
Here is a simple example that shows the problem using the default camera FOV and a single rotated quad. When the program starts, you won't see the textured quad, but you will see the bounding boxes. If you pan right the quad will appear and if you pan back left it will disappear.
Code: Select all
int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D8;
// create device and exit if creation failed
IrrlichtDevice* device =
createDevice(driverType, core::dimension2d<s32>(1024, 768));
if (device == 0)
return 1; // could not create selected driver.
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
// load the scene
const core::vector3df scl(10.f, 10.f, 10.f);
const core::vector3df rot(0.f, 35.f, 0.f);
const core::vector3df pos(0, -10.f, 0);
scene::IAnimatedMesh* mesh =
smgr->addHillPlaneMesh("floor", core::dimension2df(10.f, 10.f), core::dimension2di(1, 1));
scene::IMeshSceneNode* floor = smgr->addMeshSceneNode(mesh->getMesh(0), 0, -1, pos, rot, scl);
floor->setMaterialTexture(0, driver->getTexture("../../media/particlewhite.bmp"));
floor->setMaterialFlag(video::EMF_LIGHTING, false);
// setup the camera
scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
camera->setPosition(core::vector3df(-90.f, 18.f, 24.f));
camera->setRotation(core::vector3df(13.f, 37.f, 0.f));
// create one time materials and matrices
core::matrix4 identity;
video::SMaterial material;
material.Lighting = false;
video::SColor red(255, 255, 0, 0);
video::SColor grn(255, 0, 255, 0);
video::SColor blu(255, 0, 0, 255);
// run the simulation
while (device->run())
{
if (device->isWindowActive())
{
if (driver->beginScene(true, true, video::SColor(255,20,20,20)))
{
smgr->drawAll();
// draw boxes
driver->setTransform(video::ETS_WORLD, identity);
driver->setMaterial(material);
core::aabbox3df box;
//
// draw the fudged world aligned bounding box. notice it does
// not enclose all of the vertices of the mesh. this makes it
// possible for the cull test to cull nodes that are actually
// in view.
//
box = floor->getBoundingBox();
floor->getAbsoluteTransformation().transformBox(box);
box.MaxEdge.Y += 10.f; // give the box some height
driver->draw3DBox(box, red);
//
// draw the world aligned bounding box. notice it does include
// all of the vertices, but in some situations there is a lot
// of waste, which can cause the frustum culling to not cull
// something that it should.
//
box = floor->getBoundingBox();
floor->getAbsoluteTransformation().transformBoxEx(box);
box.MaxEdge.Y += 5.f; // give the box some height
driver->draw3DBox(box, blu);
//
// draw the object space bounding box. notice that this is the
// smallest enclosing box that is oriented with the object
// coordinate system. this is the box that should be tested
// against
//
driver->setTransform(video::ETS_WORLD, floor->getAbsoluteTransformation());
box = floor->getBoundingBox();
// no box transform needed, the verts will be transformed later
box.MaxEdge.Y += 5.f; // give the box some height
driver->draw3DBox(box, grn);
driver->endScene();
}
}
}
device->drop();
return 0;
}
The solution is to fix
CSceneManager::isCulled(). The easy way would be to change
transformBox() to
transformBoxEx(). Unfortunately that will result in obects not getting culled that should be. This is particularly a problem with slender objects, and is not so much a problem with cube shaped objects.
This is the same exact problem as the one that I ran into
here.
Travis