Page 1 of 2

[fixed in trunk] getCollisonNode() fail in IMetaTriangleSel

Posted: Sun May 05, 2013 12:53 pm
by omegasteffy
Hi there.
short:
The getCollisonNode() seem only seem able to parse the first TriangleSelector added to the IMetaTriangleSelector
What to do, am i doing stuff wrong?

Elaborated:
I would like to have a some static nodes to respresent my level/world and some movable nodes.
To get collision detection i create TriangleSelector for all nodes of the level. The smartest way is of course to gather these in a IMetaTriangleSelector

Code: Select all

IMetaTriangleSelector* assembledTriangles = smgr->createMetaTriangleSelector();
ITriangleSelector* staticTriSelector= smgr->createTriangleSelector(myStaticNode->getMesh(),myStaticNode);
ITriangleSelector* staticTriSelector2= smgr->createTriangleSelector(myStaticNode2->getMesh(),myStaticNode2);
assembledTriangles->addTriangleSelector(staticTriSelector2);
assembledTriangles->addTriangleSelector(staticTriSelector);
Afterward a CollisionResponse animator is added to my Moveable node

Code: Select all

ISceneNodeAnimatorCollisionResponse* Anim_collition = smgr->createCollisionResponseAnimator     (assembledTriangles,Node2Move, core::vector3df(5,5,5),gravity, core::vector3df(0,0,0));
    Node2Move->addAnimator(Anim_collition); 
The basic animation works. The moveable nodes are stopped by the static nodes of the level.
However in some case i would like to use a callback mechanism. (e.g. some damage might occur if a truck hit a heavy rock)
For these cases i would like to use getCollisionNode

Code: Select all

class MyColCallback:public ICollisionCallback {
    virtual bool onCollision(   const ISceneNodeAnimatorCollisionResponse &     animator    ) override
    {
        ISceneNode* Node = animator.getCollisionNode();
        std::cout<< "Callback msg. Collision with" << Node->getName() <<std::endl;
        return false;
    }
};
MyColCallback aCallBackClass;
Anim_collition->setCollisionCallback(&aCallBackClass)
However IMetaTriangleSelector parse the first node, no mater swich node i collide with

So far my best option would be to create a seperate animation for each of the staic level nodes.

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Sun May 05, 2013 7:27 pm
by zprg
in one program i had problems with triangleselector, too and changed to createTriangleSelectorFromBoundingBox and with it everything was working fine, maybe you can try?

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Sun May 05, 2013 8:59 pm
by omegasteffy
I wil give it a try. But it would not make sense. The problem is the way the IMetaTriangleSelector parse the sub-nodes. NOT indiviual triangleselectors

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Sun May 05, 2013 10:12 pm
by omegasteffy
damit it works! :-$
After i changed to use the bounding box version the correct node is picked.
To me it still be like a bug in irrlicht

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Sun May 05, 2013 11:15 pm
by zprg
yes i also think its a bug

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Mon May 06, 2013 2:52 am
by Abraxas)
IMetaTriangleSelector assembledTriangles = smgr->createMetaTriangleSelector();

But do you actually have

IMetaTriangleSelector* assembledTriangles = smgr->createMetaTriangleSelector(); ??

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Mon May 06, 2013 6:56 am
by omegasteffy
->Abraxas
I typo happened, as i tried to make reduces no. lines during copy-paste
Fixed now. However i would not even be able to compile:

Code: Select all

IMetaTriangleSelector assembledTriangles = smgr->createMetaTriangleSelector()

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Mon May 06, 2013 8:40 am
by hybrid
Can you create a simple example (full code which compiles properly) and a description how to fix the code? Otherwise it's hard to reproduce and debug this issue.

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Mon May 06, 2013 8:44 am
by omegasteffy
It is a simple example (mock-up)
https://subversion.assembla.com/svn/ver ... multiNodes
The code here works, but i have out-commented the "non-Bounding box" version
Switch back to the normal-triangle selector and it would fail.

Code: Select all

// It is not possible to get sub-nodes from the IMetaTriangleSelector if the createTriangleSelector is used
//ITriangleSelector* staticTriSelector=  smgr->createTriangleSelector(myStaticNode->getMesh(),myStaticNode);
//ITriangleSelector* staticTriSelector2= smgr->createTriangleSelector(myStaticNode2->getMesh(),myStaticNode2);
 
ITriangleSelector* staticTriSelector= smgr->createTriangleSelectorFromBoundingBox(myStaticNode);
ITriangleSelector* staticTriSelector2 = smgr->createTriangleSelectorFromBoundingBox(myStaticNode2);

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Mon May 06, 2013 11:56 pm
by omegasteffy
-> hybrid
Could you find anything wrong in this code?

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Tue May 07, 2013 6:11 am
by hybrid
No, sorry, no time yet. Well, actually I completely missed your last post somehow. But will try to test it over the holidays end of this week. Moving to bugs forum to keep this topic recognized.

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Sat Jun 29, 2013 6:51 pm
by Strong99
I can replicate this problem with almost all the collision manager methods.

My default setup:
* Metatriangle selector - total of 1500 triangles
- Triangle selector 1 - 500 triangles
- Triangle selector 2 - 1000 triangles

The issue arises when the nodes in the triangle selector are completely or are partially hidden.

Currently I see two main issues, both are related with the collision manager and the meta triangle selector classes:

Bug #1
The collision manager detects collision against the triangles within its range (line or bounding box). After collision has been detected requests the scenenode for the triangle using its index. (The index comes from the list of triangles within range/line/bbox) and tries to find the triangle id in the list with all triangles resulting that it finds a different triangle on that id.

I described two different lists of triangles the collision manager checks:
1. one which is filtered and contains the same or less triangles than list 2(<= 1500 triangles)
2. one which contains all the triangles (=1500 triangles)

If one of the scenenodes are partially or completely out of sight list 1 contains fewer triangles and thus the index won't be the same as the one in list 2.

Example for the onCollision method:
CSceneCollisionManager.h line 367, get a filtered list of triangles in range

Code: Select all

s32 cnt = 0;
selector->getTriangles(Triangles.pointer(), totalcnt, cnt, ray);
CSceneCollisionManager.h line 409, get triangle from list with all triangles where i is the index of the triangle from filtered list (list 1)

Code: Select all

selector->getSceneNodeForTriangle(i);
A logic change for me would be to include the same filters for the getSceneNodeForTriangle method, giving a ray or boundingbox with it as filter.

Code: Select all

selector->getSceneNodeForTriangle(i, ray);
Bug #2
There is also an error with the getSceneNodeForTriangle method in the CMetaTriangleSelector.h file:

Code: Select all

for (u32 i=0; i<TriangleSelectors.size(); ++i)
{
    u32 totalTriangles += TriangleSelectors[i]->getTriangleCount();
 
    if(totalTriangles > triangleIndex)
        return TriangleSelectors[i]->getSceneNodeForTriangle(0);
}
The error here is that it doesn't pass the index of the triangle to the triangleselector but 0, if the child selector is a meta triangle selector too it will always return the first node it finds rather than the one matching.

One solution could be to give the correct triangle index:

Code: Select all

for (u32 i=0; i<TriangleSelectors.size(); ++i)
{
    u32 triangles = TriangleSelectors[i]->getTriangleCount();
 
    if(totalTriangles + triangles > triangleIndex)
        return TriangleSelectors[i]->getSceneNodeForTriangle(triangleIndex - totalTriangles);
 
    totalTriangles += triangles;
}
My current solution for the collisionmanager:
I created a second method getSceneNodefromTriangleIndex taking a line3df in account:

Code: Select all

//! Return the scene node associated with a given triangle in a filtered list with as filter the line3df
ISceneNode* CMetaTriangleSelector::getSceneNodeForTriangle(u32 triangleIndex, const core::line3d<f32>& line) const
{
    u32 totalTriangles = 0;
 
    for (u32 i=0; i<TriangleSelectors.size(); ++i)
    {
        //Get the list of triangles within reach of the line
        s32 arraySize = TriangleSelectors[i]->getTriangleCount();
 
        core::array<core::triangle3df> triangles;
        triangles.set_used(arraySize);
 
        s32 trianglesCnt;
        TriangleSelectors[i]->getTriangles(triangles.pointer(), arraySize, trianglesCnt, line);
 
        //Default picking based on triangle count, note: also reducing the index for the local selector, otherwise the next selector can's search a subset
        if(totalTriangles + trianglesCnt > triangleIndex)
            return TriangleSelectors[i]->getSceneNodeForTriangle(triangleIndex - totalTriangles, line);
 
        totalTriangles += trianglesCnt;
    }
 
    // For lack of anything more sensible, the index is not here
    return 0;
}
[edit] Added a solution from my custom irrlicht 1.8 build

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Fri Jul 05, 2013 8:55 pm
by zprg
good job strong99 sounds you found the ugly bugs in the collision! when will it be in the next irrlichtversion?

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Fri Jul 05, 2013 10:01 pm
by polylux
Had some similar issue about three years ago. Bit in a hurry atm so I can't confirm it's the same issue. Maybe related?

Re: Collision bug? getCollisonNode() fail with IMetaTriangle

Posted: Fri Jul 05, 2013 11:18 pm
by Strong99
@polylux they seem closely related as well as the link you provided with an other bugfix by LexManos on #bug1. I can't explain your bug though, as it sounds like you always received the terrain even though it is the last selector added.

@zprg I haven't created a patch for it yet but I'll post one as soon as possible.