Page 1 of 2

[fixed] Issue with collision

Posted: Tue Oct 27, 2009 5:03 am
by crosel
Hi,

Im not sure if its just me or not but when i use the function:

getCollisionPoint()

I have inconsisten results. What is strange is, the fact that the results do not occur in 1.5 but only in 1.6

Pretty much, what i do is create a "ray" between a camera and its look at position. It then calls this function based on that ray.

Yet sometimes, something strange happens, in which it wont get the correct object or "end" position. The ray seems to pass through the object im after.

Yet if i move myself (the camera) to a different position, it will work. So it seems depending upon the position of the object, it sometimes work's.

Hope this make sense.

The code is based off the Demo example for shooting, with only small alterations to it to suit my needs.

Does this happen to anyone else?

Cheers.

Posted: Tue Oct 27, 2009 6:18 am
by MarvLeonidasX
Yes I have almost the same problem, but mine is distance based not positional: The node the ray intersects with is only "detected" if the camera is really close to said node. But in 1.51 the collision detection behaves as it should. Now some may say, "Well, if it works in 1.51 but not 1.6 then just use 1.51!" But 1.51 had other issues that 1.6 fixed.

Maybe 1.61+ will fix this collision problem without breaking something else...

Posted: Tue Oct 27, 2009 8:56 am
by hybrid
We would need a simply setup which can reproduce the problem. Maybe you can also collect some values which could give a hint about what might fail here. I'll move this thread to the bug forum for confirmation.

Posted: Tue Oct 27, 2009 6:34 pm
by vitek
I haven't tested this against 1.5.1, but it does exhibit some interesting behavior.

Code: Select all

#include <irrlicht.h> 
using namespace irr;

#include <stdio.h>

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

int main() 
{ 
  // create device and exit if creation failed 
  IrrlichtDevice *device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(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(); 

  // add camera 
  scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
  camera->setPosition(core::vector3df(30, 30, 30));
  camera->setTarget(core::vector3df(-8.f, 8.f, -8.f));
  camera->setID(0);

  // add a dynamic light (this causes weirdness)
  smgr->addLightSceneNode(0, core::vector3df(4, 4, 4), video::SColorf(.2f, .3f, .2f)); 

  // add a cube to pick
  scene::ISceneNode* cube = smgr->addCubeSceneNode(15);

  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();

        driver->endScene(); 
      }

      gui::ICursorControl* cursor = device->getCursorControl();
      const core::position2di pos(cursor->getPosition().X, cursor->getPosition().Y);

      // get the line used for picking
      core::line3df ray =
        smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(pos, camera);

      // find a selected node
      scene::ISceneNode* pick = 
        smgr->getSceneCollisionManager()->getSceneNodeFromRayBB(ray, 1);

      core::matrix4 invMat = cube->getAbsoluteTransformation();
      invMat.makeInverse();

      invMat.transformVect(ray.start);
      invMat.transformVect(ray.end);

      const int a_hit = (pick == cube);
      const int b_hit = cube->getBoundingBox().intersectsWithLine(ray);

      wchar_t buf [32];
      _snwprintf (buf, sizeof buf / sizeof *buf, L"%d:%d", a_hit, b_hit);

      device->setWindowCaption(buf);
    } 
  } 

  device->drop(); 

  return 0; 
} 
The testcase does a ray intersection test against a cube in two different ways. It uses the collision manager and a quick box/ray collision check. Ideally, the colon seperated string in the title bar should always be 0:0 because there is no collision, or 1:1 indicating there is a collision. If the two values aren't the same then one of the collision detection techniques isn't working correctly. I frequently see 0:1 which indicates the collision manager isn't detecting the collision.

Travis

Posted: Thu Nov 05, 2009 7:40 am
by mmxx1
Hi,

I've noticed that in my application after upgrade irrlicht engine from 1.5.1 to 1.6, function getSceneNodeFromScreenCoordinatesBB works not completely right.
In my app (shows houses with adding furnitures function) I have orbit camera with zoom function, I've noticed that when i decrease distance (radius) from camera to furniture (added earlier to the scene) function getSceneNodeFromScreenCoordinatesBB recognizes it and works fine, but when I increase distance from camera to the added sceneNode, function getSceneNodeFromScreenCoordinatesBB doesn't see my node under mouse position.
I must fly with my camera relatively close to the node to pick it by mouse.

I use this code :

Code: Select all


irr::scene::ISceneNode* sn = smgr->getSceneCollisionManager()->getSceneNodeFromScreenCoordinatesBB(
						irr::core::position2d<irr::s32>(
device->getCursorControl()->getPosition().X,
device->getCursorControl()->getPosition().Y
),
1<<30,
false,
0
);
if(sn) 
{
...
}
....
[/code]

Posted: Thu Nov 05, 2009 8:47 am
by hybrid
Yes, this method calls getSceneNodeFromRayBB internally, so would show similar problems. The method which seems to have made the change is getPickedNodeBB, which is used by all the other methods.
Edit: Found the problem. It's the early out block in line 104, which does an object space test with isPointInside. When disabling this test the example runs without problems. I hope vitek can explain what's wrong with this part :wink:

Posted: Thu Nov 05, 2009 10:04 am
by mmxx1
Great that this part of irrlicht functionality has been fixed :)
Hope official fix release 1.6.1 will be available soon, because my app is a commercial product.
Greetings

Posted: Thu Nov 05, 2009 10:31 am
by hybrid
I'll probably just disable that part in 1.6, as fixing the code might introduce even more problems. Depends on the necessary code changes. Anyway, 1.6.1 will have this fixed some way.

Posted: Thu Nov 05, 2009 10:50 pm
by vitek
hybrid wrote:I hope vitek can explain what's wrong with this part :wink:
I'll have to take some time to look at it. The logic seems reasonable, but the start of the ray most definitely should not be inside the bounding box in my testcase.

Travis

Posted: Sun Dec 06, 2009 9:54 pm
by Mequa
hybrid wrote:Yes, this method calls getSceneNodeFromRayBB internally, so would show similar problems. The method which seems to have made the change is getPickedNodeBB, which is used by all the other methods.
Edit: Found the problem. It's the early out block in line 104, which does an object space test with isPointInside. When disabling this test the example runs without problems. I hope vitek can explain what's wrong with this part :wink:
I can confirm that this fixes the problem. The file in question here is (from the extracted archive) irrlicht-1.6\source\Irrlicht\CSceneCollisionManager.cpp , from line 104:

if(objectBox.isPointInside(objectRay.start))
{
// If the line starts inside the box, then consider the distance as being
// to the centre of the box.
const f32 toIntersectionSq = objectRay.start.getDistanceFromSQ(objectBox.getCenter());
if(toIntersectionSq < outbestdistance)
{
outbestdistance = toIntersectionSq;
outbestnode = current;

// And we can truncate the ray to stop us hitting further nodes.
ray.end = ray.start + (rayVector * sqrtf(toIntersectionSq));
}
}
else if (objectBox.intersectsWithLine(objectRay))
{
.............

To fix this, simply comment out the relevant section of code so it looks like this:

/*if(objectBox.isPointInside(objectRay.start))
{
// If the line starts inside the box, then consider the distance as being
// to the centre of the box.
const f32 toIntersectionSq = objectRay.start.getDistanceFromSQ(objectBox.getCenter());
if(toIntersectionSq < outbestdistance)
{
outbestdistance = toIntersectionSq;
outbestnode = current;

// And we can truncate the ray to stop us hitting further nodes.
ray.end = ray.start + (rayVector * sqrtf(toIntersectionSq));
}
}
else */ if (objectBox.intersectsWithLine(objectRay))
{
.............

Save the file, then open Irrlicht.dev (for Dev-CPP) or Irrlicht9.0.vcproj (for Visual Studio 2008), Release (not Debug) mode, and select Rebuild All.
(You may also need to install the latest DirectX SDK for Direct3D9 support, plus an older version if you want to build support for Direct3D8, and add the relevant Include and Library directories).

Assuming the process completed successfully, the fixed Irrlicht.dll will be found in the appropriate folder under irrlicht-1.6\bin\ (either Win32-gcc or Win32-VisualStudio).
Copy this over to your game/application's working folder (or alternatively static link), and voila! Working bounding box collisions even between the camera's line of view and billboard nodes (as my app required), which I can confirm was broken in the 1.6 build I downloaded and fixed by this method...

Posted: Sun Dec 06, 2009 9:59 pm
by hybrid
Ah yes, almost forgot about this problem. I've disabled the test for now, just as shown above. We'll have to check this later on.

Posted: Sun Dec 13, 2009 11:52 pm
by hybrid
Please note that I had to revert this change, as it caused another regression. Thus I'm not sure if this issue can be fixed in 1.6, or will have to wait for 1.7.

Posted: Mon Dec 14, 2009 7:28 am
by mmxx1
What consequences (damages) in other parts of Irrlicht will bring this change in CSceneCollisionManager.cpp ?

Posted: Mon Dec 14, 2009 5:26 pm
by hybrid
Which change, the first one proposed or my revert? The revert undid all changes made between 1.6 release and now, so the situation will be the same as for the official SDK. I don't know which things are broken since then exactly, I've seen just one so far (as documented above).

Posted: Tue Dec 15, 2009 9:31 am
by mmxx1
So what is your suggestion to fix this - come back to 1.5.1 or comment (if(objectBox.isPointInside(objectRay.start)) .... ) CSceneCollisionManager.cpp or wait for 1.7 (how long) ?