So the interesting workaround I found is:
Change the method recomputeAABB() in collicion_kernel.h to stop
checking the gflags.
void recomputeAABB() {
// if (gflags & GEOM_AABB_BAD) {
// our aabb functions assume final_posr is up to date
recomputePosr();
computeAABB();
gflags &= ~GEOM_AABB_BAD;
// }
}
The result problem (when waiting for gflags to become bad) is that the
AABB used in GIMPACT is not updated never collides with the plane
(checked in gim_trimesh_plane_collision(..) ). Actually, it does
collide, but only much later after it sunk in deeply. I'm not sure why
so much later it decides to finally update the AABB. Does it maybe
wait until it leaves the AABB of the heightfield?
I also found that dGeomMoved() (collision_space.cpp) is never called
on the TriMesh after creation. It is only repeatedly called for the
Ray used by the heightfield collider.
The workaround is obviously not a good solution, and I have no idea
why dGeomMoved() is never called (or is that intended?).
I'm a bit stuck now, could maybe someone shed some light on this? Any
suggestions?
Many thanks,
Tilmann
=============
www.ode4j.org
=============
dGeomMoved() is called unconditionally for *every* geom attached to a
body (see util.cpp). If you are sure it's not being called for the
trimesh (which I assume is attached to a body) then the only explanation
is a memory corruption coming from somewhere else. You might have to
fire up a debugger and/or a memory analyzer like valgrind, see if there
are any invalid memory accesses. It's probably in the gimpact-specific
code, as opcode seems to not be affected.
--
Daniel K. O.
"The only way to succeed is to build success yourself"
But I don't think that is the case, because the same problem occurs in
my Java port of ODE/GIMPACT, and I believe Java is largely immune
against memory corruption. Above that, the problem disappears (and
dGeomMoved() is called again) once the trimesh gets away from the
heightfield (this may be coincidence(?)).
I was more thinking that the heigthfield collider may substitute the
trimesh-geom with the ray-geom that it creates for collision, for
performance reasons, could that be the case? I couldn't find any peace
of code that does that, however.
Tilmann
Okay, it seems I made a mistake regarding dGeomMoved(), it is indeed
called. I also checked that a body is attached.
That leaves the curios behaviour that the problem is fixed when
recalculating the AABB even if the objects is not 'bad'.
Any ideas?
Thanks,
Tilmann
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org
iEYEARECAAYFAktYnOoACgkQ6CnElG/gOPd0uQCgwdUBLjn4YKm4VUDKCFK1QtlF
PwEAoNBACASfnvuAmbnngaU0dzFvKqxS
=PUj0
-----END PGP SIGNATURE-----
Well, then I don't know what your test case is. I was testing on the
heightfield demo; just forcing the AABB recomputation isn't enough to
keep GIMPACT trimesh from falling through. Additionally, the
heightfield code does some changes directly on the geom's transforms,
so that's a bit suspicious too. Are you sure the AABB is problematic
when the collision fails? The OPCODE's AABBs are not as tight, maybe
it suffers from the same problem depending on the dimensions involved.
Thanks for looking into this :-)
I just check it again, my test case is demo_heightfield in ode 0.11.1,
using GIMPACT (--with-trimes=gimpact). I tried both DOUBLE and SINGLE,
no other options.
I'm on Linux 64bit, using gcc 4.3.2, if that matters.
Just to avoid misunderstandings, the bunny will think partly through
the heightfield (it doesn't do that in my Java port, so I don't mind).
I'm interested in the part once it bounced of the heightfield and hits
the Plane.
Normally the Bunny topples over, sinks almost completely into the plane,
then resurfaces and stabilizes.
Removing the 'if' statement in recomputeAABB() prevents it from sinking
(visibly) into the plane. It still stabilizes in a somewhat unrealistic
position though.
Otherwise the code is not modified.
If you can't see it, let me know whether you a different platform.
Maybe it's a 32/64bit issue???
Cheers,
Tilmann
Daniel K. O. wrote:
> 2010/1/21 Tilmann Z�schke <zaes...@gmx.de>:
>> Okay, it seems I made a mistake regarding dGeomMoved(), it is indeed
>> called. I also checked that a body is attached.
>>
>> That leaves the curios behaviour that the problem is fixed when
>> recalculating the AABB even if the objects is not 'bad'.
>> Any ideas?
>
> Well, then I don't know what your test case is. I was testing on the
> heightfield demo; just forcing the AABB recomputation isn't enough to
> keep GIMPACT trimesh from falling through. Additionally, the
> heightfield code does some changes directly on the geom's transforms,
> so that's a bit suspicious too. Are you sure the AABB is problematic
> when the collision fails? The OPCODE's AABBs are not as tight, maybe
> it suffers from the same problem depending on the dimensions involved.
>
>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.9 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org
iEYEARECAAYFAktY2ecACgkQ6CnElG/gOPdUeQCgpaWSNSemDHY8OvzB1wjYvpmH
qvsAoJ03swSj/wnSj/xNEYQJAkx2qZ62
=+/rn
-----END PGP SIGNATURE-----
Just as a reminder, the fix does not prevent the bunny (press 'm' in
demo_heightfield) from going through the heightfield. But it prevents
the Bunny from submerging into the ground after it bounced off the
heightfield.
A simple fix (not very performant and somewhat dirty) is to insert the
following three lines into heightfield.cpp (lines 1817-1819, latest from
SVN):
#if dTRIMESH_GIMPACT
o2->computeAABB();
#endif
Explanation:
The dCollideHeightfield(...) function changes pos,R,aabb and flags of
a colliding object to some temporary values. It then calls (line 1741)
the computeAABB() method.
// Rebuild AABB for O2
if (reComputeAABB)
o2->computeAABB();
In the lines above the proposed (dirty?) fix, it tries to revert the
temporary change and overwrites pos,R,aabb, and flags with backup values.
The problem in GIMPACT (I don't know about OPCODE) is, that
computeAABB() also changes the AABB stored internally in GIMPACT.
But the attempt to revert the changes only restores the AABB in the
Geom, not the one in GIMPACT. Hence GIMPACT uses the wrong AABB in the
next collision, until it is calculated again.
Some possible ways of fixing this are:
- backup the GIMPACT-AABB as well and restore it later.
- do not call computeAABB() in 1741, calculate the temporary in a
different way, e.g. by transforming the existing AABB with the same
matrix that would turn POS into the tempPOS and R into tempR (the
temporary values)
- call computeAABB() after restoring the values (but that may have
impact on performance)
- Possibly unreasonable effort: Avoid transforming 'o2' at all,
but transform the plane of the heightfield (see my question below).
Question: To be honest, I do not understand why the colliding objects
are moved around at all. Could someone shed some light on this and maybe
explain why this is done (e.g. instead of transforming the plane,
which is probably less effort)?
Also, shall I provide a patch?
Any comments are appreciated.
Thanks,
Tilmann
For this "dirty" variant I doubt the patch file is necessary. If you decide
to make a complete "legal" fix, the patch would be appreciated of course.
Oleh Derevenko
-- Skype with underscore
#if dTRIMESH_GIMPACT
if (o2->type==dTriMeshClass)
o2->computeAABB();
#endif
Tilmann
Ok, I can see it happening here too.
> The problem in GIMPACT (I don't know about OPCODE) is, that
> computeAABB() also changes the AABB stored internally in GIMPACT.
> But the attempt to revert the changes only restores the AABB in the
> Geom, not the one in GIMPACT. Hence GIMPACT uses the wrong AABB in the
> next collision, until it is calculated again.
It seems the heightfield code is at fault here. GIMPACT only receives
position and orientation updates during the AABB computation. As the
geom was "moved" for the collision test, it should make sure the geom is
"moved back" to the original position.
> Some possible ways of fixing this are:
> - backup the GIMPACT-AABB as well and restore it later.
The issue might not be GIMPACT-specific. Any external collision
detection library that you try to plug in might suffer from this.
> - do not call computeAABB() in 1741, calculate the temporary in a
> different way, e.g. by transforming the existing AABB with the same
> matrix that would turn POS into the tempPOS and R into tempR (the
> temporary values)
I think the proper fix here is that we should have an computeOBB() that
receives an arbitrary transform. By default it can return the AABB's
AABB, according with the new orientation, and the geoms would override it.
> Question: To be honest, I do not understand why the colliding objects
> are moved around at all. Could someone shed some light on this and maybe
> explain why this is done (e.g. instead of transforming the plane,
> which is probably less effort)?
If the heightfield has an arbitrary orientation, how can you figure out
which cells you should test? One simple way is to have the BB of the
geom aligned with the heightfield (so you can enumerate these cells with
2 nested loops). It's also possible to just project the AABB's to the
heightfield plane, but it requires more code, and is probably less
efficient.
I can see spheres are quite bad in approximating lengthy geoms. But
for other geoms (cylinders, pyramids,.. ) they are not much worse than
boxes, and for others (short capsules, spheres, rock-shaped
trimeshes,...) they probably fit even better than boxes.
They are probably hard to calculate for geoms like trimeshes, but the
real advantage would be that they would be invariant over the lifetime
of a geom, independent of it's rotation, only depending on the position.
So I could imagine in case of the heightfield collider, which does a lot
of AABB rotation, they might perform better than boxes?
In the meanwhile, I will have a look at implementing the computeOBB().
How to make this work:
a)
Do initial checking with a temporary AABB (OBB) in
dCollideHeightfield(..), but then refactor
dxHeightfield::dCollideHeightfieldZone(...) to call the colliders with
the un-transformed geom and a transformed plane instead.
OR
b)
Alternatively, the refactor dCollideHeightfield(..) to use
dGeomSetPosition() and dGeomSetRotation() for the temporary
transformation, instead of directly accessing the variables. This is
somewhat expensive, but would make sure that the geom-objects know about
the updates.
I think a) would be a bit more work, but may result in faster code.
Any comments?
Cheers,
Tilmann
But these functions would also trigger space updates, which are locked
during the broad phase. A work-around is doable, but I believe a) is
the proper way to do it.
I have a question though, I noticed the following in heigthfield.cpp
1728-1729:
dMultiply1_331( pos1, terrain->final_posr->R, pos0 );
dMultiply1_333( R1, terrain->final_posr->R, o2->final_posr->R );
However dxGeom.computePosr() in collision_kernel.cpp (421-425) the pos
is calculated by also adding the bodies' position.
dMultiply0_331 (final_posr->pos,body->posr.R,offset_posr->pos);
final_posr->pos[0] += body->posr.pos[0];
final_posr->pos[1] += body->posr.pos[1];
final_posr->pos[2] += body->posr.pos[2];
dMultiply0_333 (final_posr->R,body->posr.R,offset_posr->R);
Excuse my ignorance, but could it be that one of the above is not
correct? Shouldn't the heigthfield consider the bodies position as well?
Cheers,
Tilmann
On 28/01/10 21:32, Daniel K. O. wrote:
> 2010/1/28 Tilmann Z�schke <tilma...@gmx.de>:
I have created a patch (ID 2963676):
https://sourceforge.net/tracker/?func=detail&aid=2963676&group_id=24884&atid=382801
For me it fixes the problem of the trimesh sinking into the ground after
bouncing off the heightfield.
It touches a number of files, mostly the heightfield collider, but also
many geometry classes for which it made sense to implement a dedicated
oriented bounding box function.
Please let me know what you think.
Best regards,
Tilmann
My idea is the one that I've expressed in the comment for the patch.In my opinion the rotation for o2 should be eliminated altogether and heightfield should not be rotated either. The heightfield surface is just the set of planes each of them having a very simple constraint on contact points to be located in axis aligned right-angled triangle (well in coordinates of heightfield or in coordinates of the plane - I'm not sure what is the correct approach here but either way should not be difficult). As far as I know, the plane-object collision checking does not require object rotation. So, why the heightfield does?Ff the main difficulty is because the existing plane-object colliders need to be reused, then, instead of rotating object it could be possible to pass space transformation matrix+vector as the optional parameter to collider functions and account them in end-formulas if they are present. In any case, don't try to convince me that trimesh (whether it is GIMPACT or OPCODE) can't check collisions with plane that is arbitrarily rotated.
----- Original Message -----From: Tilmann Zaeschke
Sent: Tuesday, April 27, 2010 12:10 AMSubject: Re: [ode-users] GIMPACT problemsOn 26.04.2010 09:42, Oleh Derevenko wrote:My idea is the one that I've expressed in the comment for the patch.In my opinion the rotation for o2 should be eliminated altogether and heightfield should not be rotated either. The heightfield surface is just the set of planes each of them having a very simple constraint on contact points to be located in axis aligned right-angled triangle (well in coordinates of heightfield or in coordinates of the plane - I'm not sure what is the correct approach here but either way should not be difficult). As far as I know, the plane-object collision checking does not require object rotation. So, why the heightfield does?Ff the main difficulty is because the existing plane-object colliders need to be reused, then, instead of rotating object it could be possible to pass space transformation matrix+vector as the optional parameter to collider functions and account them in end-formulas if they are present. In any case, don't try to convince me that trimesh (whether it is GIMPACT or OPCODE) can't check collisions with plane that is arbitrarily rotated.
Thanks for the feedback.
I didn't write the heightfield collider, but I believe the explanation is as follows (as I also commented on the patch):
Leaving the planes flat and instead turning the object allows for very fast collision checking of an AABB with an horizontal plane, it doesn't get much faster than that (and you don't get any false positives).
----- Original Message -----From: "Tilmann Zäschke"Sent: Monday, May 03, 2010 8:48 PMSubject: Re: [ode-users] GIMPACT problems
Anyway, when the rotation is updated, all AABBs are updated. And this
GIM_AABB_SET is directly used by the colliders.
So there are two problems here:
- Whoever wanted to use temporary rotation/AABBs would need to
understand when and how this locking and pointer swizzling works.
- I believe that leaves the problem that all the AABBs in the
GIM_AABB_SET would need to be recalculated, which costs time and extra
storage space (one AABB per triangle).
Say you want to simulate certain rebel infiltrators getting crushed in a star destroyer's thrash compactor