Culling with Parents?
Culling with Parents?
Hi,
I have a grid of terrain "chunks" which are parented to one object (to easily rotate and position).
When I rotate around the yaw to a value between 0 and 90 (43 in this case), the culling on the chunks becomes very strange.
Below is a screenshot, the chunks appear to disappear in a line.
Does anyone know what might be happening, and how to fix it?
Thanks in Advance!
I have a grid of terrain "chunks" which are parented to one object (to easily rotate and position).
When I rotate around the yaw to a value between 0 and 90 (43 in this case), the culling on the chunks becomes very strange.
Below is a screenshot, the chunks appear to disappear in a line.
Does anyone know what might be happening, and how to fix it?
Thanks in Advance!
What version of Irrlicht are you using [svn or 1.2]? It looks as if the nodes are being culled. Possibly the bounding boxes of the nodes are wrong, or the function that does the culling has some sort of bug. Are these custom scene nodes, or are they just terrain scene nodes or mesh scene nodes? Do you have your own custom cull method or are you just using the culling provided by Irrlicht?
Travis
Travis
Those bounding boxes don't look right to me. They are much taller than they should be. The bounding box should be the smallest object aligned box that all of the vertices can fit into. Are you loading a model from file? I'm assuming you are loading a model from file, and if so, I would guess that the problem is with your model.
I did some testing with Irrlicht 1.2 and I don't see the problem. I tested with both animated mesh nodes and just plain mesh scene nodes. No problem noticed.
I did some testing with Irrlicht 1.2 and I don't see the problem. I tested with both animated mesh nodes and just plain mesh scene nodes. No problem noticed.
Code: Select all
core::dimension2df tileSize(100.f, 100.f);
core::dimension2di tileCount(1, 1);
f32 hillHeight = 0.f;
core::dimension2df hillCount(0.f, 0.f);
core::dimension2df textureRepeat;
textureRepeat.Height = 1.f; // tileCount.Height / tileSize.Height;
textureRepeat.Width = 1.f; // tileCount.Width / tileSize.Width;
video::ITexture* textures[8];
textures[0] = driver->getTexture("../../media/portal1.bmp");
textures[1] = driver->getTexture("../../media/particlered.bmp");
textures[2] = driver->getTexture("../../media/portal3.bmp");
textures[3] = driver->getTexture("../../media/particlewhite.bmp");
textures[4] = driver->getTexture("../../media/portal5.bmp");
textures[5] = driver->getTexture("../../media/particlered.bmp");
textures[6] = driver->getTexture("../../media/portal7.bmp");
textures[7] = driver->getTexture("../../media/particlewhite.bmp");
scene::IAnimatedMesh* mesh =
smgr->addHillPlaneMesh("floor", tileSize, tileCount, 0, hillHeight, hillCount, textureRepeat);
if (mesh)
{
u32 x, z;
for (x = 0; x < 20; ++x)
{
for (z = 0; z < 20; ++z)
{
const core::vector3df pos(x * 100.f, -10.f, z * 100.f);
//scene::IAnimatedMeshSceneNode* floor = smgr->addAnimatedMeshSceneNode(mesh, 0, -1, pos);
scene::IMeshSceneNode* floor = smgr->addMeshSceneNode(mesh->getMesh(0), 0, -1, pos);
if (floor)
{
floor->setMaterialTexture(0, textures[ rand() & 0x7 ]);
floor->setMaterialFlag(video::EMF_LIGHTING, false);
floor->setDebugDataVisible(true);
}
}
}
}
I think you're talking about the software driver. It doesn't render triangles that are intersected by the frustrum. You can tell by the screenshot that this is not the case. It does not clip the tris on the left or front, only on the right edge of the screen.
Are you doing anything special with the camera? Can you provide a link to your 'model' so that I can try it out first hand?
Travis
Are you doing anything special with the camera? Can you provide a link to your 'model' so that I can try it out first hand?
Travis
I was reading about multithreading in games and it turns out clipping is a problem since sometimes diffrent parameters are updated ansychronosly(i cant spell ) they advised to do what blindside did and compensate by making the clipping frutsum larger (he did this using the fov) so no artiffacts occur, till he next chance of proper synch is available.
"Irrlicht is obese"
If you want modern rendering techniques learn how to make them or go to the engine next door =p
If you want modern rendering techniques learn how to make them or go to the engine next door =p
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.
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
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;
}
This is the same exact problem as the one that I ran into here.
Travis