[fixed]getCollisionPoint() has gaps at large distances

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.
dixx
Posts: 15
Joined: Sat Sep 03, 2011 5:04 pm
Location: Leipzig, Germany

[fixed]getCollisionPoint() has gaps at large distances

Post by dixx »

Hello all!

First of all: great engine, great forum! I use Irrlicht for some time now and found always help here when I needed some.
Until now; I saw some strange behaviour of getCollisionPoint() with the following setup:
- load mesh from .3ds file, scale it * 200
- place it far away, about 39000 Irrlicht units from zero point (position(0,0,0))
- create IMeshNode from mesh
- create octree triangle selector from node
- add a camera
Now, in the main loop, I cast a ray from the camera's position straight down through the mesh node (from above bbox to below bbox) and check for a collision point.
When I move the camera with the cursor keys and the mouse, sometimes I do not get a collision with the mesh! There are no holes in the mesh, and when I place it at short distance to zero point, I always get my collision point. The farther away I place my node, the more gaps I get during camera movement.
Is that,like, expected behaviour due to some engine limitations, ore like a floating point issue, or just my dirty code?

Thanks in advance and Best Regards,
dixx
dixx
Posts: 15
Joined: Sat Sep 03, 2011 5:04 pm
Location: Leipzig, Germany

Re: getCollisionPoint() has gaps at large distances

Post by dixx »

Here is the code of a sample app to reproduce the behaviour:

Code: Select all

 
/**
 * @file    getCollisionPointWithScalesMesh_Test.cpp
 * @date    04.06.2012
 * @author  dixx
 * @brief   Test to locate gaps (points where getCollisionPoint() returns no
 *          point) within a scaled mesh
 *
 *  Additional information:
 *      Irrlicht Engine version 1.7.2
 *      Microsoft Windows XP Professional Service Pack 2 (Build 2600)
 *      Using renderer: OpenGL 3.3.0
 *      GeForce GTS 250/PCI/SSE2/3DNOW!: NVIDIA Corporation
 *      OpenGL driver version is 1.2 or better.
 *      GLSL version: 3.3
 */
 
#include <irrlicht.h>
 
using namespace irr;
 
 
 
f32 getHeight( const f32 x, const f32 z,
        scene::ISceneCollisionManager* colliman,
        scene::IMeshSceneNode* testNode )
{
    core::vector3df collisionPoint = core::vector3df();
    core::triangle3df collisionTriangle = core::triangle3df();
    const scene::ISceneNode* collisionNode;
 
    // cast a ray from above the bbox of our testNode straight down
    // and return the height of the mesh at the given xz coordinates
    // or 1000.0f if no collision point was found.
    if ( colliman->getCollisionPoint(
            core::line3df(
                    x, testNode->getTransformedBoundingBox().MaxEdge.Y+1.0f, z,
                    x, testNode->getTransformedBoundingBox().MinEdge.Y-1.0f, z
            ),
            testNode->getTriangleSelector(),
            collisionPoint, collisionTriangle, collisionNode ) )
    {
        return collisionPoint.Y;
    }
    else
    {
        return 1000.0f;
    }
}
 
 
// from the 04.Movement example
class MyEventReceiver : public IEventReceiver
{
public:
    // This is the one method that we have to implement
    virtual bool OnEvent(const SEvent& event)
    {
        // Remember whether each key is down or up
        if (event.EventType == irr::EET_KEY_INPUT_EVENT)
            KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
 
        return false;
    }
 
    // This is used to check whether a key is being held down
    virtual bool IsKeyDown(EKEY_CODE keyCode) const
    {
        return KeyIsDown[keyCode];
    }
 
    MyEventReceiver()
    {
        for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
            KeyIsDown[i] = false;
    }
 
private:
    // We use this array to store the current state of each key
    bool KeyIsDown[KEY_KEY_CODES_COUNT];
};
 
 
 
int main()
{
    scene::IMesh* testMesh;
    scene::IMeshSceneNode* testNode;
    scene::ITriangleSelector* selector;
    core::matrix4 matrix = core::matrix4();
    scene::ICameraSceneNode* camera;
    core::vector3df cameraOffset = core::vector3df( 0.0f, 2.0f, 0.0f );
 
    MyEventReceiver receiver;
    IrrlichtDevice* device = createDevice( video::EDT_OPENGL,
            core::dimension2du( 800, 600 ), 32, false, true, false,
            &receiver );
    if ( device == 0 ) exit( 1 );
    video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr  = device->getSceneManager();
    scene::IMeshManipulator* meshManipulator = smgr->getMeshManipulator();
    scene::ISceneCollisionManager* colliman = smgr->getSceneCollisionManager();
 
    // load, scale and place mesh
    driver->setTransform( video::ETS_WORLD, core::matrix4() );
    testMesh = meshManipulator->createMeshCopy(
            smgr->getMesh( "just_a_mesh.3ds" ) );
    matrix.setScale( core::vector3df(
            200.0f + 0.001f, 200.0f, 200.0f + 0.001f ) );
    matrix.setTranslation(
            core::vector3df(
                    99 * 400.0f + 200.0f,
                    0.0f,
                    99 * 400.0f + 200.0f
            )
    );
    meshManipulator->transform( testMesh, matrix );
    meshManipulator->recalculateNormals( testMesh, true );
 
    // setHardwareMappingHint
    for ( register u32 i = 0; i < testMesh->getMeshBufferCount(); ++i )
    {
        scene::IMeshBuffer* buffer = testMesh->getMeshBuffer( i );
        buffer->setHardwareMappingHint( scene::EHM_STATIC );
        buffer->setDirty();
        buffer->recalculateBoundingBox();
    }
 
    // create node from mesh
    testNode = smgr->addMeshSceneNode( testMesh );
    testMesh->drop();
 
    // set material
    testNode->setMaterialTexture(
            0, driver->getTexture( "just_a_texture.jpg" ) );
    testNode->setMaterialType( video::EMT_SOLID );
    testNode->setMaterialFlag( video::EMF_LIGHTING, false );
    testNode->setVisible( true );
 
    // add node to collision detection
    selector = smgr->createOctreeTriangleSelector(
            testNode->getMesh(), testNode, 900 );
    testNode->setTriangleSelector( selector );
    selector->drop();
 
    // add a camera
    camera = smgr->addCameraSceneNodeFPS( 0, 360.0f, 0.01f );
    camera->setPosition( core::vector3df(39936.0f, 0.0f, 39755.0f) );
    camera->setTarget( camera->getPosition() + core::vector3df( 1.0f, 0.0f, 1.0f ) );
    camera->updateAbsolutePosition();
    camera->setFarValue( 300.0f );
    camera->setNearValue( 0.1f );
    camera->setFOV( 1.25f );
    camera->setAspectRatio( 4.0f / 3.0f );
    camera->setInputReceiverEnabled( true );
    smgr->setActiveCamera( camera );
    device->getCursorControl()->setVisible( false );
 
    while( device->run() )
    {
        if ( !device->isWindowActive() ) device->yield();
        if ( receiver.IsKeyDown( irr::KEY_ESCAPE ) ) device->closeDevice();
 
        core::vector3df pos = camera->getPosition() - cameraOffset;
        pos.Y = getHeight( pos.X, pos.Z, colliman, testNode );
        if ( pos.Y > 999.0f ) printf( "gap at x=%f, z=%f!\n", pos.X, pos.Z );
        camera->setPosition( pos + cameraOffset );
 
        driver->beginScene( true, true );
        smgr->drawAll();
        driver->endScene();
    }
 
    device->drop();
    return 0;
}
 
The mesh can be found at https://github.com/dixx/getCollisionPoi ... sMesh_Test
CuteAlien
Admin
Posts: 9670
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: getCollisionPoint() has gaps at large distances

Post by CuteAlien »

Hm, thanks for the test. Unfortunately I need a model now which works with that test... I tried room.3ds from the media-folder but that just gives me a black screen with this code.

I have one bug still left to fix before Irrlicht release about collision, but that was for a very extreme corner-case (and caused by floating point troubles). No idea right now if your problem is related. Certainly not expected to miss collisions.

edit: OK, sorry - didn't see the mesh-link at first. Will try again.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
smso
Posts: 246
Joined: Fri Jun 04, 2010 3:28 pm
Location: Hong Kong

Re: getCollisionPoint() has gaps at large distances

Post by smso »

Draw the bounding box of the node and the ray for testing collision. Then use a second camera to see if something is wrong.

Regards,
smso
CuteAlien
Admin
Posts: 9670
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: getCollisionPoint() has gaps at large distances

Post by CuteAlien »

I can reproduce it with your test, but debugging that will take a while and I can't do that now. But it looks a lot like the triangle bug which I'm already hunting (the currently outcommented part in testTriangle3d in the triangle3d.cpp test). I had a solution for that already, but it broke some other stuff, so working on a new solution. It's a combination of several floating-point troubles actually and one of the handful problems left before we can release 1.8. I'll check your test-case again once I found a better solution for this problem.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
dixx
Posts: 15
Joined: Sat Sep 03, 2011 5:04 pm
Location: Leipzig, Germany

Re: getCollisionPoint() has gaps at large distances

Post by dixx »

CuteAlien, thanks alot for your answer (and the time already invested)!
Would you think it may help to downscale my whole world (collision problem is related to a little game project) or would that result in the same floating point issues? And if I can help with anything (except for debugging) please give me a shout.
smso, thank you too, but bboxes and ray seem to be correct all the time (I did the draw-and-look-from-behind test already).
CuteAlien
Admin
Posts: 9670
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: getCollisionPoint() has gaps at large distances

Post by CuteAlien »

Sorry don't know about scaling. My old fix was here: http://irrlicht.sourceforge.net/forum/v ... 2&p=263477
(the lines marked as fix). I think the trouble was that this won't work when used with integer types. If you want you can try if that would already solve your problem. But I think I'll probably get to it in a few days anyway.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
CuteAlien
Admin
Posts: 9670
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: getCollisionPoint() has gaps at large distances

Post by CuteAlien »

Please try again with newest svn trunk. I checked-in several fixes in revision 4183 and it seems to work with your test so far.
Unless we find another problem it will stay like this and be in Irrlicht 1.8 soon.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
nespa
Posts: 167
Joined: Wed Feb 24, 2010 12:02 pm

Re: getCollisionPoint() has gaps at large distances

Post by nespa »

no bug, try with :

Code: Select all

      node->setTriangleSelector(selector);
        selector->drop();
        scene::ISceneCollisionManager* collMan = smgr->getSceneCollisionManager();
        core::line3d<f32> ray;
        ray.start = camera->getPosition();
        ray.end = ray.start + (camera->getTarget() - ray.start).normalize() * 30000.0f;//see here the distance
        core::vector3df intersection;
        core::triangle3df hitTriangle;
        scene::ISceneNode * outNode =
                        collMan->getSceneNodeAndCollisionPointFromRay(
                                        ray,
                                        intersection, // This will be the position of the collision
                                        hitTriangle, // This will be the triangle hit in the collision
                                        1<<0, // This ensures that only nodes that we have
                                                        // set up to be pickable are considered
                                        0); // Check the entire scene (this is actually the implicit default)
 



where ray:

Code: Select all

       
                core::line3d<f32> ray;
        ray.start = camera->getPosition();
        ray.end = ray.start + (camera->getTarget() - ray.start).normalize() * 30000.0f; // larger is better
 
CuteAlien
Admin
Posts: 9670
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: getCollisionPoint() has gaps at large distances

Post by CuteAlien »

@nespa: I don't know how to interpret your message. With "no bug", do you mean "no, there is a bug"? If so - your code is without any context - I just don't see how it fits into the example above. If it has to do with the example above please explain. If not - then please post a complete example where I can reproduce any problem (I have have no idea what kind of node you have there for example).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
nespa
Posts: 167
Joined: Wed Feb 24, 2010 12:02 pm

Re: getCollisionPoint() has gaps at large distances

Post by nespa »

I think it is about the setting the size of the ray; if the ray is too short, it doesn't collide his mesh.
CuteAlien
Admin
Posts: 9670
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: getCollisionPoint() has gaps at large distances

Post by CuteAlien »

I have the feeling we're not talking about the same right now nespa. I did fix a problem in triangle3d which caused the trouble in the code from dixx (and some troubles in other test-cases). That fix is now in latest svn trunk and I'm just wondering if I did catch all cases.

I guess you meant there was no bug in the original code, but that's not correct, there was indeed a problem in Irrlicht caused by some floating point inaccuracies that caused it to miss collisions sometimes when they hit polygons exactly on the border.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
dixx
Posts: 15
Joined: Sat Sep 03, 2011 5:04 pm
Location: Leipzig, Germany

Re: getCollisionPoint() has gaps at large distances

Post by dixx »

CuteAlien, nespa, thanks for your help and ideas. I would like to try with newest svn trunk, but am not sure where to go and what to do for this, could you please give me a hint?
dixx
Posts: 15
Joined: Sat Sep 03, 2011 5:04 pm
Location: Leipzig, Germany

Re: getCollisionPoint() has gaps at large distances

Post by dixx »

@nespa: I start my ray above the highest point of mesh's bbox and end it below the lowest point of bbox. Should be long enough :)
CuteAlien
Admin
Posts: 9670
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: getCollisionPoint() has gaps at large distances

Post by CuteAlien »

You first have to get an svn-client. If you are on Windows I would recommend installing TortoiseSVN while on Linux systems I usually use the commandline tools (package name depends on distribution, but usually something like "subversion").

Then on the commandline you can use: svn co https://irrlicht.svn.sourceforge.net/sv ... icht/trunk irrlicht
That will write the trunk (which contains always the version in development) into the folder irrlicht.
With Tortoise on Windows you will have a the svn-client directly in the file-browser and can checkout with right-click (and again need servername like above and some target-folder where you want to put it).
Once you have checked out once you can always update with "svn update" or with TortoiseSVN by right-clicking the folder and selecting update.

You can also browse svn-folders online here: http://sourceforge.net/projects/irrlicht/develop
(note that they give another path to use for check-out which does not contain /trunk, but that will download all versions ever released of Irrlicht which you usually do not want).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply