why only check x/y rotation when prerender terrain?

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
fatfatson
Posts: 2
Joined: Mon Dec 22, 2008 3:49 pm

why only check x/y rotation when prerender terrain?

Post by fatfatson »

i see the code in void CTerrainSceneNode::preRenderLODCalculations():

Code: Select all

		// Only check on the Camera's Y Rotation
		if (!ForceRecalculation)
		{
			if (( fabs(cameraRotation.X - OldCameraRotation.X) < CameraRotationDelta) &&
				( fabs(cameraRotation.Y - OldCameraRotation.Y) < CameraRotationDelta))
			{
				if ((fabs(cameraPosition.X - OldCameraPosition.X) < CameraMovementDelta) &&
					(fabs(cameraPosition.Y - OldCameraPosition.Y) < CameraMovementDelta) &&
					(fabs(cameraPosition.Z - OldCameraPosition.Z) < CameraMovementDelta))
				{
					return;
				}
			}
		}
i'm confusing by both the comment and the code. the code show it only cocerns about x/y, and the comment says "only Y".
but why do they all ignore "Z"?...
thanks very much..
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

You didn't copy/paste an important part of the code...

Code: Select all

  560 		const core::vector3df cameraRotation = core::line3d<f32>(cameraPosition, SceneManager->getActiveCamera()->getTarget()).getVector().getHorizontalAngle();
The Z part of cameraRotation is always 0. So checking this wouldn't be very useful.

If I'm reading the code in core::vector3d<>::getHorizontalAngle() correctly, it isn't really giving the horizontal angle, but the rotation around the X and Y axes (i.e., the camera yaw and pitch).

The reason that the Z rotation (the roll) isn't taken into account is that the algorithm thinks that a rotation on Z won't affect which patches are visible. Unfortunately, I don't believe that this actually correct. When the camera is rotated on the Z axis, the frustum is rotated. If the frustum is rotated, the corners of the frustum might expose areas of terrain that were culled previously.

I think that this code was written to work with the FPS camera, and AFAICT the FPS camera doesn't handle roll rotations well, so this scenerio wasn't tested.

If it is indeed a bug, it would be trivial to write a testcase.
  1. add a terrain scene node.
  2. add a camera scene node.
  3. put the camera at the top-center of the terrain bounding box.
  4. set the camera target to the center of the bounding box.
  5. set the up vector to core::vector3df(0.f, 0.f, 1.f).
  6. in the render loop, rotate the up vector (only the X and Z components, Y will always be 0.f).
If the terrain is chopped off when the camera is rotated, then this is a bug. If you don't write a testcase, I'll submit one later this morning...

Travis
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I say it's a bug. The following code shows it pretty clearly...

Code: Select all

#include <irrlicht.h>
using namespace irr;

#ifdef _IRR_WINDOWS_
#  pragma comment(lib, "Irrlicht.lib")
#endif

int main()
{
    IrrlichtDevice *device =
        createDevice(video::EDT_BURNINGSVIDEO);

    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
    irr::ITimer* timer = device->getTimer();

    scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( 
        "../../media/terrain-heightmap.bmp");
    terrain->setScale(core::vector3df(40.f, .1f, 40.f));

    terrain->setMaterialFlag(video::EMF_LIGHTING, false);
    terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg"));
    terrain->setDebugDataVisible(scene::EDS_FULL);

    scene::ICameraSceneNode* camera = smgr->addCameraSceneNode();

    const core::vector3df center (terrain->getBoundingBox().getCenter());
    camera->setTarget (center);

    // yes, Y is intentionally being set to X here
    const core::vector3df above (center.X, center.X, center.Z);
    camera->setPosition (above);

    // put the camera at a height so that the terrain is just inside
    // the view frustum. the height of the terrain above zero is what
    // makes the terrain visible
    camera->setFarValue (above.Y);

    const u32 period = 2500;

    // when the current time is more than `when' we rotate the
    // camera
    u32 when = timer->getTime() + period;

    // this alternates from 0 to 1 and back every `period' ms
    u32 flip = 0;

    while(device->run())
    {
        const u32 now = timer->getTime();
        if (when < now) {
            when = now + period;
            flip ^= 1;
        }

        if (flip) {
            const core::vector3df up (.707f, 0.f, .707f);
            camera->setUpVector(up);
        }
        else {
            const core::vector3df up (1.f, 0.f, 0.f);
            camera->setUpVector(up);
        }

        if (driver->beginScene(true, true, video::SColor(255,100,101,140)))
        {
            smgr->drawAll();

            driver->endScene();
        }
    }

    device->drop();

    return 0;
}
Normally the camera zfar value is much larger than is necessary. This artificially blows up the size of the frustum bounding box. This unnecessarily causes patches of terrain that are not visible to be included in the render buffer (it might be good to do frustum tests on each patch instead of frustum box tests).

This testcase sets the terrain to be right at the edge of the view frustum far plane, and this makes the frustum box as small as possible while keeping the terrain in view. When the camera is rotated, you see the boxes for the patches that were not included in the render buffer the last time that the LOD values were calculated.

Travis
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Just a note that this now in the tracker. Thanks for the great bug report, and as always, anyone is welcome to take a poke at providing a fix. ;)
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

This should be fixed in SVN 2003 (trunk) and SVN 2004 (1.5 branch). If it is, thank Travis' excellent test case. Any remaining errors are mine.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

rogerborg wrote:If it is, thank Travis' excellent test case.
Thanks. I'm trying to set an example.

Hopefully people will take a hint and start writing simple testcases like this. It makes problems much easier to debug if you don't have to reproduce them yourself.

Travis
Post Reply