gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Fixed point ray plane collision

#163820 - 3dfx - Sun Oct 12, 2008 11:28 pm

Hey guys I'm using the ray plane collision test based on http://www.flipcode.com/archives/Point-Plane_Collision.shtml .
And I'm having a rough time getting it working properly.

Code:

typedef struct {
     int32 x, y, z;
}VECTOR32;

typedef struct {
   VECTOR32 points[4];
   VECTOR32 normal;
   int d;
}Plane;


void calcPlaneD(Plane *plane){
   plane->d = dotProd(&plane->points[0], &plane->normal);
}
void calcPlaneNormal(Plane *plane){
   VECTOR32 points[2];
   points[0].x = plane->points[1].x - plane->points[0].x;
   points[0].y = plane->points[1].y - plane->points[0].y;
   points[0].z = plane->points[1].z - plane->points[0].z;
   
   points[1].x = plane->points[2].x - plane->points[1].x;
   points[1].y = plane->points[2].y - plane->points[1].y;
   points[1].z = plane->points[2].z - plane->points[1].z;
   
   plane->normal.x = mulf32(points[0].y, points[1].z) - mulf32(points[1].y, points[0].z);
   plane->normal.y = mulf32(points[0].z, points[1].x) - mulf32(points[1].z, points[0].x);
   plane->normal.z = mulf32(points[0].x, points[1].y) - mulf32(points[1].x, points[0].y);
   normalizeVector(&plane->normal);
}

int32 dotProd(VECTOR32 *one, VECTOR32 *two)
{
   return mulf32(one->x, two->x) + mulf32(one->y, two->y) + mulf32(one->z, two->z);
}
void normalizeVector(VECTOR32 *vec)
{
   // magnitude = sqrt ( Ax^2 + Ay^2 + Az^2 )
   int32 magnitude = sqrtf32( mulf32(vec->x, vec->x) + mulf32(vec->y, vec->y) + mulf32(vec->z, vec->z) );

   vec->x = divf32(vec->x, magnitude);
   vec->y = divf32(vec->y, magnitude);
   vec->z = divf32(vec->z, magnitude);
}
int distToIntersection(Plane *plane, VECTOR32 *startingPt, VECTOR32 *dir){  //
   int32 denom = dotProd(&plane->normal, dir);
   if(absV(denom == 0)){
      return -1;
   }
   int numer = dotProd(&plane->normal, startingPt) + plane->d;
   return (-div32(numer, denom));
}


It seems to only work when the normal is 0, 4096, 0.
I checked it(made it print out stuff) and seems like distToIntersection doesnt give me the right result. Any ideas why?

#163821 - silent_code - Sun Oct 12, 2008 11:39 pm

What does absV in "if(absV(denom == 0))" mean?
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.

#163822 - 3dfx - Sun Oct 12, 2008 11:43 pm

Whoops typo, it's if absV(denom) == 0) well i wasnt checking for 0 as much as I was gonna check for less than a small value.
So I meant absV(denom) < smallVal;

#163860 - TwentySeven - Mon Oct 13, 2008 10:14 pm

Code:

void calcPlaneNormal(Plane *plane){
   VECTOR32 CA;
   VECTOR32 CB;

   //C-A
   CA.x = plane->points[2].x - plane->points[0].x;
   CA.y = plane->points[2].y - plane->points[0].y;
   CA.z = plane->points[2].z - plane->points[0].z;
   
   //C-B
   CB.x = plane->points[2].x - plane->points[1].x;
   CB.y = plane->points[2].y - plane->points[1].y;
   CB.z = plane->points[2].z - plane->points[1].z;
 
    //crossprod
    plane->normal.x = mulf32(CA.y,CB.z) - mulf32(CA.z, CB.y);
    plane->normal.y = mulf32(CA.z, CB.x) - mulf32(CA.x, CB.z);
    plane->normal.z = mulf32(CA.x, CB.y) - mulf32(CA.y, CB.x);

    normalizeVector(&plane->normal);
}


Thats just modified after checking it against my own functions. Your math *may* be correct but I'm absolutely sure that is ^

#163861 - TwentySeven - Mon Oct 13, 2008 10:28 pm

The other issue is that your addition inside your normalize function could be overflowing..

#163862 - 3dfx - Mon Oct 13, 2008 11:14 pm

Thanks for the help. Doing the cross prod your way didnt change anyhting unfortunately, but I was changing my coordinates randomly to see if it would do anything. Also my coordinates are small values (none larger than (7<<12)).

And oddly enough, the points (0, 0, -7), (0, 0, 7), (7, 0, 7), (7,0, -7) in fixed pt would give the normal (-2896, 2896, 0). So far so good. When using the collision with this plane, it worked!

But using the points (0, 0, -7), (0, 0, 7), (7, 7, 7), (7,7, -7) gave the proper normal of 2896 2896 but the collision would be wrong, that is, the collision distance was far too great. The distance was actually the distance it would be if the plane was upside down.
So I'm largely confused why the first set of coordinates works.
My position is above the plane in the ydir and within the plane coordinates in the x and z direction. My direction vector is (0,-4096,0).

#163864 - TwentySeven - Mon Oct 13, 2008 11:53 pm

Could you be running into winding order issues then?

#163869 - 3dfx - Tue Oct 14, 2008 2:19 am

I have no clue why, but setting the plane's d to -d solved all my problems.
Weird stuff. I'd love to know why, but I guess I have to content myself with a solution. :D

Thanks all!

#163903 - silent_code - Tue Oct 14, 2008 8:08 pm

Maybe it's because of
Code:
distance = |ax + by + cz + d|

and
Code:
d = a + b + c
with (a,b,c) normalized

I have only glanced over your implementation, though.

Check your absV, too.
_________________
July 5th 08: "Volumetric Shadow Demo" 1.6.0 (final) source released
June 5th 08: "Zombie NDS" WIP released!
It's all on my page, just click WWW below.

#163919 - sajiimori - Wed Oct 15, 2008 3:56 am

3dfx, try doing the math by hand for a very simple case, like the x=2 plane (that is, n=(1,0,0) and d=-2), and a ray going along -x from (3,0,0).

Quick sanity checks like that usually get the basic test working, leaving only degenerate cases to deal with.