hi,
i am completely new to collision detection and physics libraries, so please bear with me...
for the first step i want to do a simple ray world collision detection for selection purposes. i had a look at the collision inferface demo and i think i get the basics. now my question is how to simply use bullet collision detection to just test all world objects against a single ray and get the nearest collision object to the starting point of the ray (eye position)?
my second question would be if bullet is using the GIMPACT library implicitly for such collision detection or do i have to specify the use of GIMPACT directly for collision tests against concave objects?
thanks for the help...
-chris
p.s.
i saw that i have to specify the solver directly for physics simulation/constraint resolving. i couldn't find information about which solver i should use for which purpose in terms of efficiency?
simple ray-world collision detection
-
- Site Admin
- Posts: 4221
- Joined: Sun Jun 26, 2005 6:43 pm
- Location: California, USA
When using Bullet, it is easiest to use the built-in raycast functionality. Mouse picking is using raycasting, see CcdPhysicsDemo, and Bullet/Demos/OpenGL/DemoApplication.cpp for implementation. Use the ClosestRayResultCallback to find the first hit. This is implemented in btCollisionWorld (and derived classes like btDiscreteDynamicsWorld).
Bullet (and Havok, Ageia PhysX) don't recommend using moving concave triangle meshes. It is better to use compound objects (convex decomposition). But if you really intend to use moving concave triangle meshes, you can use GIMPACT. See MovingConcaveDemo for an integration. The updated GIMPACT 0.2 is integrated in Bullet Subversion repository as Extras, so it will be available in next Bullet version 2.54.
It is best to stick with the default constraint solver. There is a option to choose ODE quickstep solver, but only contact constraints are hooked up (constraints/motors/limits are todo).
Hope this helps,
Erwin
Code: Select all
/// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback);
It is best to stick with the default constraint solver. There is a option to choose ODE quickstep solver, but only contact constraints are hooked up (constraints/motors/limits are todo).
Hope this helps,
Erwin
-
- Posts: 3
- Joined: Fri Jun 22, 2007 6:39 am
ok, i will have a look at the svn version with GIMPACT 0.2.Erwin Coumans wrote:Bullet (and Havok, Ageia PhysX) don't recommend using moving concave triangle meshes. It is better to use compound objects (convex decomposition). But if you really intend to use moving concave triangle meshes, you can use GIMPACT. See MovingConcaveDemo for an integration. The updated GIMPACT 0.2 is integrated in Bullet Subversion repository as Extras, so it will be available in next Bullet version 2.54.
i thought bullet uses GIMPACT implicitly for collision tests and i would not have to care about its integration. are there cases where it is better to use bullets own collision detection over GIMPACTs?
-
- Site Admin
- Posts: 4221
- Joined: Sun Jun 26, 2005 6:43 pm
- Location: California, USA
In all cases I recommend to just stick with Bullet's collision detection: Bullet doesn't use GIMPACT by default, it is just an optional extension.
Bullet handles collisions and raycasting against box, sphere, triangle, convex, cone, cylinder, static triangle mesh or compound shape natively without using GIMPACT.
There is one exception: when you need to have moving concave objects, it is recommended to decompose them (automatically or manually) into convex pieces and add them into a btCompoundShape. You can also use GIMPACT for moving concave triangle meshes (if you cannot or don't want to decompose your moving concave object for some reason), but a btCompoundShape is the preferred solution.
Thanks,
Erwin
Bullet handles collisions and raycasting against box, sphere, triangle, convex, cone, cylinder, static triangle mesh or compound shape natively without using GIMPACT.
There is one exception: when you need to have moving concave objects, it is recommended to decompose them (automatically or manually) into convex pieces and add them into a btCompoundShape. You can also use GIMPACT for moving concave triangle meshes (if you cannot or don't want to decompose your moving concave object for some reason), but a btCompoundShape is the preferred solution.
Thanks,
Erwin
-
- Posts: 14
- Joined: Thu Jun 28, 2007 2:26 pm
RayTest problems
Do not use RayTest if you are looking for an accurate way to get the exact point of contact.
I've been having problems with RayTest so I stepped into it. It would seem they are first testing against an aabb with RayAabb to see if it passes through the objects bounding box. This works fine. However, it is in RayTestSingle that looks like it checks against a sphere? In my case, I have a long box I am trying to get the coord my ray is hitting the aabb. However, it only detects it if the ray is pretty close to the center, and even then, the hit point is usually above the object. To their credit, there is a comment that says they should move RaytestSingle into a method on CollisionObject, and they are right.
I've been having problems with RayTest so I stepped into it. It would seem they are first testing against an aabb with RayAabb to see if it passes through the objects bounding box. This works fine. However, it is in RayTestSingle that looks like it checks against a sphere? In my case, I have a long box I am trying to get the coord my ray is hitting the aabb. However, it only detects it if the ray is pretty close to the center, and even then, the hit point is usually above the object. To their credit, there is a comment that says they should move RaytestSingle into a method on CollisionObject, and they are right.
-
- Site Admin
- Posts: 4221
- Joined: Sun Jun 26, 2005 6:43 pm
- Location: California, USA
Re: RayTest problems
You should be able to use RayTest for finding the intersection of a ray against objects in the btCollisionWorld.Zimbarbo wrote:Do not use RayTest if you are looking for an accurate way to get the exact point of contact.
It sweeps a sphere of radius 0 (= point) againt all objects that overlap the aabb with the ray. It is using the collision margin, so that might explain why the intersection point is slightly above the box. Also, there is an accuracy threshold that causes another very small approximation. We could make this user-tunable. We could move the raycast to the btCollisionShape class, then the user can override the RayTest with a more accurate/custom version.
Hope this helps,
Erwin
-
- Posts: 14
- Joined: Thu Jun 28, 2007 2:26 pm
More detail
Ok, thanks, that does make more sense. However, I still see horrible results. I will try stepping into the SubsimbplexConvexCast's CalctimeOfImpact to see what is happening because in my example here is what I get:
(X,Y,Z)
I have a collision object with an Aabb (and actual coords since it is a box) of
Min - (69,73,-10)
Max - (261, 100, 20)
I shoot a ray:
From: (105, 24, 0)
To: (304, 224, 0)
I get a hit point of (217,136,0)
136(Y) is more than a little bit above 100(Y), which is pretty bad.
And when I shoot the ray;
From (51, 38, 0)
To (251, 238, 0)
It doesn't hit at all. The collision of dynamic objects against this box are spot on. I have another box I can control and fly around it, and it hits and interacts perfectly, so I know my rigidbody and graphical representation is fine. There is just either something wrong with what I am expecting from the ray test, or something wrong with the ray test.
Thanks for the reply and explanation, though!
(X,Y,Z)
I have a collision object with an Aabb (and actual coords since it is a box) of
Min - (69,73,-10)
Max - (261, 100, 20)
I shoot a ray:
From: (105, 24, 0)
To: (304, 224, 0)
I get a hit point of (217,136,0)
136(Y) is more than a little bit above 100(Y), which is pretty bad.
And when I shoot the ray;
From (51, 38, 0)
To (251, 238, 0)
It doesn't hit at all. The collision of dynamic objects against this box are spot on. I have another box I can control and fly around it, and it hits and interacts perfectly, so I know my rigidbody and graphical representation is fine. There is just either something wrong with what I am expecting from the ray test, or something wrong with the ray test.
Thanks for the reply and explanation, though!
-
- Site Admin
- Posts: 4221
- Joined: Sun Jun 26, 2005 6:43 pm
- Location: California, USA
Is this XNA C# or C++? If C++, can you create a reproducing case in one of the Bullet demos (for example Raytracer demo)
If it is XNA / C#, it might be a porting bug. I will create a Bullet XNA / C# forum, to avoid confusion. Can you make sure to report XNA/C# bugs here?
http://www.codeplex.com/xnadevru/WorkItem/List.aspx
Thanks,
Erwin
If it is XNA / C#, it might be a porting bug. I will create a Bullet XNA / C# forum, to avoid confusion. Can you make sure to report XNA/C# bugs here?
http://www.codeplex.com/xnadevru/WorkItem/List.aspx
Thanks,
Erwin
-
- Posts: 14
- Joined: Thu Jun 28, 2007 2:26 pm
My Solution
because I am just dealing with Aabb, I made a simple function to test a ray against it and find the hitpoint. The intersection code came right from GraphicsGems, so I tried not to alter it, and I give it credit here.
Code: Select all
public bool HitBoundingBox( Vector3 vMinBox, Vector3 vMaxbox, Vector3 vFrom, Vector3 vDir, out Vector3 vHitPoint )
{
//char HitBoundingBox(minB,maxB, origin, dir,coord)
//double minB[NUMDIM], maxB[NUMDIM]; /*box */
//double origin[NUMDIM], dir[NUMDIM]; /*ray */
//double coord[NUMDIM]; /* hit point */
//{
int NUMDIM = 3;
int LEFT = 1;
int RIGHT = 0;
int MIDDLE = 2;
float[] minB = { 0.0f, 0.0f, 0.0f };
float[] maxB = { 0.0f, 0.0f, 0.0f };
float[] origin = { 0.0f, 0.0f, 0.0f };
float[] dir = { 0.0f, 0.0f, 0.0f }; /*ray */
float[] coord = { 0.0f, 0.0f, 0.0f };
vHitPoint = Vector3.Zero;
minB[0] = vMinBox.X; minB[1] = vMinBox.Y; minB[2] = vMinBox.Z;
maxB[0] = vMaxbox.X; maxB[1] = vMaxbox.Y; maxB[2] = vMaxbox.Z;
origin[0] = vFrom.X; origin[1] = vFrom.Y; origin[2] = vFrom.Z;
dir[0] = vDir.X; dir[1] = vDir.Y; dir[2] = vDir.Z;
bool inside = true;
float[] quadrant = { 0.0f, 0.0f, 0.0f };
int i;
int whichPlane;
float[] maxT = { 0.0f, 0.0f, 0.0f };
float[] candidatePlane = { 0.0f, 0.0f, 0.0f };
/* Find candidate planes; this loop can be avoided if
rays cast all from the eye(assume perpsective view) */
for (i=0; i<NUMDIM; i++)
if(origin[i] < minB[i]) {
quadrant[i] = LEFT;
candidatePlane[i] = minB[i];
inside = false;
}else if (origin[i] > maxB[i]) {
quadrant[i] = RIGHT;
candidatePlane[i] = maxB[i];
inside = false;
}else {
quadrant[i] = MIDDLE;
}
/* Ray origin inside bounding box */
if(inside) {
coord = origin;
vHitPoint.X = coord[0];
vHitPoint.Y = coord[1];
vHitPoint.Z = coord[2];
return (true);
}
/* Calculate T distances to candidate planes */
for (i = 0; i < NUMDIM; i++)
if (quadrant[i] != MIDDLE && dir[i] !=0.0f)
maxT[i] = (candidatePlane[i]-origin[i]) / dir[i];
else
maxT[i] = -1.0f;
/* Get largest of the maxT's for final choice of intersection */
whichPlane = 0;
for (i = 1; i < NUMDIM; i++)
if (maxT[whichPlane] < maxT[i])
whichPlane = i;
/* Check final candidate actually inside box */
if (maxT[whichPlane] < 0.0f) return (false);
for (i = 0; i < NUMDIM; i++)
if (whichPlane != i) {
coord[i] = origin[i] + maxT[whichPlane] *dir[i];
if (coord[i] < minB[i] || coord[i] > maxB[i])
return (false);
} else {
coord[i] = candidatePlane[i];
}
vHitPoint.X = coord[0];
vHitPoint.Y = coord[1];
vHitPoint.Z = coord[2];
return (true); /* ray hits box */
}
public bool RayTest( RigidBody bodyBox, Vector3 from, Vector3 to, out Vector3 hitPoint )
{
Boolean foundHit = false;
hitPoint = Vector3.Zero;
DiscreteDynamicsWorld physics = (DiscreteDynamicsWorld)(game.Services.GetService(typeof(DiscreteDynamicsWorld)));
Vector3 currentHitPoint = new Vector3();
float minRayLength = float.MaxValue;
float currentRayLength = float.MaxValue;
Vector3 collisionObjectAabbMin, collisionObjectAabbMax;
float hitLambda = 1f;
Vector3 hitNormal = new Vector3();
Vector3 vDir = to - from;
vDir.Normalize();
foreach (CollisionObject collisionObject in physics.CollisionObjects)
{
collisionObject.CollisionShape.GetAabb(collisionObject.WorldTransform, out collisionObjectAabbMin, out collisionObjectAabbMax);
// Quick function to cull out many objects. might now be needed since hitboundingbox does about the same thing.
if (XnaDevRu.BulletX.MathHelper.RayAabb(from, to, collisionObjectAabbMin, collisionObjectAabbMax, hitLambda, hitNormal))
{
RigidBody body = RigidBody.Upcast(collisionObject);
if (!ReferenceEquals(body, bodyBox))
{
bool bHit = HitBoundingBox(collisionObjectAabbMin, collisionObjectAabbMax, from, vDir, out currentHitPoint);
if (bHit)
{
Vector3 vLength = currentHitPoint - from;
currentRayLength = vLength.Length();
if( currentRayLength < minRayLength )
{
minRayLength = currentRayLength;
hitPoint = currentHitPoint;
foundHit = true;
}
}
}
}
}
return foundHit;
}
-
- Site Admin
- Posts: 4221
- Joined: Sun Jun 26, 2005 6:43 pm
- Location: California, USA
This forum is mainly for Bullet C++ version.
For questions/feedback/contribution to the C# version, please visit codeplex:
http://www.codeplex.com/xnadevru/Wiki/V ... Title=Home
Thanks,
Erwin
For questions/feedback/contribution to the C# version, please visit codeplex:
http://www.codeplex.com/xnadevru/Wiki/V ... Title=Home
Thanks,
Erwin
-
- Posts: 2
- Joined: Sun Nov 25, 2007 4:09 am
Re: simple ray-world collision detection
Note: apologies for bumping this old thread, but I do have a relevant reply (perhaps an admin could prepend "XNA" or something to the subject line to avoid confusion?)
Ray-casts against non-rotated boxes work perfectly. Ray-casts against rotated boxes (even a slight rotation of 1 degree) give very wild results.
I wish I had a solution for you, but I don't - this is just a confirmation of the bug (which was presumably a result of porting). I don't have time to look further at the bug, as I really want to move on with development of my hobby game, so for now it's flat collision only for me Suffice to say I'd be pretty grateful if someone did take a look at it.
Cheers,
Will
I have had the same experience with the XNA port of Bullet. I recently ported the Raycast Vehicle class which I needed, and along the way hit up against this problem.Ok, thanks, that does make more sense. However, I still see horrible results. I will try stepping into the SubsimbplexConvexCast's CalctimeOfImpact to see what is happening because in my example here is what I get:
Ray-casts against non-rotated boxes work perfectly. Ray-casts against rotated boxes (even a slight rotation of 1 degree) give very wild results.
I wish I had a solution for you, but I don't - this is just a confirmation of the bug (which was presumably a result of porting). I don't have time to look further at the bug, as I really want to move on with development of my hobby game, so for now it's flat collision only for me Suffice to say I'd be pretty grateful if someone did take a look at it.
Cheers,
Will