Sliding collision, lil help

Started by
4 comments, last by Cakey 14 years, 10 months ago
Alright, so here's the environment. C# XNA. The First colliding object is a BoundingSphere around my camera the second is a simple AABB(BoundingBox). Here's what I have so far:


                    BoundingBox AABB = worldCollision;
                    if (cameraSphere.Contains(AABB) != ContainmentType.Disjoint){
                        //The Sphere and the AABB collide

                        //1.Get closest coord from sphere
                        Vector3 collisionOrigin = ClosestPointOnAABB(fpCam.Position, AABB);
                        //2.Calculate sliding plane normal
                        Vector3 planeNormal = fpCam.Position - collisionOrigin;
                        planeNormal.Normalize();
                        //3.Get last Vector transformation done on the Camera
                        float Velocity = fpCam.lastMovementVector().Length();
                        //Calculate new location to move
                        Vector3 pushVelocity = planeNormal * Velocity;
                        //Set new location
                        fpCam.Position += pushVelocity;
 
                    }
I'm not sure exactly what I'm doing wrong. It works, and it works, but it is really bouncy and jumpy. Any ideas why? [Edited by - Cakey on June 10, 2009 4:59:02 PM]
Advertisement
newer code less jittery but still has some error or something. Any ideas?
BoundingBox AABB = worldCollision;                    if (cameraSphere.Contains(AABB) != ContainmentType.Disjoint){                        //The Sphere and the AABB collide                        //1.Get closest coord from sphere                        Vector3 collisionOrigin = ClosestPointOnAABB(fpCam.Position, AABB);                        //2. Get the overlapping value of the intersection                        Vector3 getOverLap = collisionOrigin - fpCam.Position;                        float penetrationDepth = (float)Math.Sqrt((getOverLap.X * getOverLap.X +                                                getOverLap.Y * getOverLap.Y +                                                getOverLap.Z * getOverLap.Z));                        //3. Subtract Overlap from Colliding sphere size                        penetrationDepth = minimumDistance + penetrationDepth;                        //4. Calculate sliding plane normal                        Vector3 planeNormal = fpCam.Position - collisionOrigin;                        planeNormal.Normalize();                        //5.Get last Vector transformation done on the Camera                        float Velocity = fpCam.lastMovementVector().Length() * penetrationDepth;                        //6. Calculate new location to move                        Vector3 pushVelocity = planeNormal * Velocity;                        //Set new location                        fpCam.Position += pushVelocity;                    }
There are a couple of things about the code that are a bit inaccurate and/or confusing. Here's the code with a few comments added to point to some of the problem areas:

BoundingBox AABB = worldCollision;if (cameraSphere.Contains(AABB) != ContainmentType.Disjoint){    // Some of your variable names are a little unclear, which makes    // the code hard to follow. I'll point them out as I go, starting    // with 'collisionOrigin' (I kind of see what you're getting at,    // but I would just call it 'closestPoint').    Vector3 collisionOrigin = ClosestPointOnAABB(fpCam.Position, AABB);    // There's some redundancy here in that you compute the vector from the    // closest point to the sphere center twice (reversed the second time).    // You also compute its length twice. These computations can be combined,    // which will tighten up the code and make it a bit more efficient.        // 'getOverlap' is another confusing variable name (it's an object, but    // the name includes a verb). Also, it's not the overlap, but rather the    // 'inverse' of the overlap (sort of). Maybe 'difference' instead?    Vector3 getOverLap = collisionOrigin - fpCam.Position;        // You should never code common operations such as computing the length    // of a vector manually like this; make a 'length' function instead. In    // addition to making the code easier to debug, it'll make it easier    // to read as well; this statement, for example, will become:        // float penetrationDepth = getOverlap.Length();    float penetrationDepth = (float)Math.Sqrt((getOverLap.X * getOverLap.X +                            getOverLap.Y * getOverLap.Y +                            getOverLap.Z * getOverLap.Z));    /// What's 'minimumDistance'? Is that the sphere's radius?    penetrationDepth = minimumDistance + penetrationDepth;    // This is the duplication I was talking about (you've already    // computed the negative of this vector, and its length, so you    // don't need to do it again here).    Vector3 planeNormal = fpCam.Position - collisionOrigin;    planeNormal.Normalize();    // The name 'Velocity' is incorrect (also, the capitilization is    // inconsistent, which is confusing). A velocity has a speed and direction;    // this variable should just be called 'speed'.    float Velocity = fpCam.lastMovementVector().Length() * penetrationDepth;    // I would have to spend a little time with this to    // understand what it is you're doing exactly, but I have a    // feeling (which could be wrong) that it's incorrect. Cleaning    // up the code will make it much easier to tell what's going    // on though.    Vector3 pushVelocity = planeNormal * Velocity;    fpCam.Position += pushVelocity;}
Yes the minimumDistance is the boundingSpheres radius.


here's the fixes you suggested:
//The Sphere and the AABB collide                            //1.Get closest coord from sphere                            Vector3 closestPoint = ClosestPointOnAABB(fpCam.Position, AABB);                            //2. Get the overlapping value of the intersection                            Vector3 difference = closestPoint - fpCam.Position;                            float penetrationDepth = minimumDistance - difference.Length();                            //4. Calculate sliding plane normal                            Vector3 planeNormal = fpCam.Position - closestPoint;                            planeNormal.Normalize();                            //5.Get last Vector transformation done on the Camera                            float speed = fpCam.lastMovementVector().Length() * penetrationDepth;                            //6. Calculate new location to move                            Vector3 pushVelocity = planeNormal * speed;                            //Set new location                            fpCam.Position += pushVelocity;


For some reason this code is NOT jittery. and appears to work but is the equation wrong? What if I collided on the y-axis?

[Edited by - Cakey on June 10, 2009 5:06:16 PM]
To be honest I can't quite figure out what your code is supposed to do (maybe I'm just missing something).

The following code is similar to yours, but instead resolves the intersection by displacing the sphere using the minimum translational vector (not compiled or tested). Note also that I removed a few calculations that were redundant:

Vector3 closestPoint = ClosestPointOnAABB(fpCam.Position, AABB);Vector3 difference = fpCam.Position - closestPoint;float length = difference.Length();float penetrationDepth = minimumDistance - length;Vector3 planeNormal = difference / length;// Resolve intersection:fpCam.Position += planeNormal * penetrationDepth;
if your camera hit's a wall it's supposed to just keep sliding but not go through the wall. I figured it out now though. Thanks a bunch!

This topic is closed to new replies.

Advertisement