• 14
• 15
• 11
• 10
• 9

# point outside of a brush problem

This topic is 4861 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I've got a pretty decent .Map file parser, but theres just one little bug that is keeping me from making shapes other than cubes... I need to be able to test whether or not a vertice is outside of a given brush, and I've got this fucntion to do just that:

typedef enum pointPos {PLANE_FRONT, PLANE_BACK, PLANE_COINCIDE} pointPos;

pointPos classifyPoint(FACE *face, Vector3 *point)
{
float p = scalarProduct(&face->normal, point) + face->distance;

if( p > 0.0f ) return PLANE_FRONT;
if( p < 0.0f ) return PLANE_BACK;

return PLANE_COINCIDE;
}


but the problem is, it thinks that 4 of the vertices of my actual cube (and these are correct vertices that should coincide) are outside of it...but they are not. is there something wrong with my code or is there an error in my math?

##### Share on other sites
You have to add an epsilon value.

if(p > -MY_EPSILON && p < MY_EPSILON)
return COINCIDE;

if(p < 0.0f)
return BACK;
else
return FRONT;

##### Share on other sites
what is epsilon? (besides the letter E)

##### Share on other sites
Epsilon can be thought of as the smallest delta that wouldn't affect the outcome of some process.

Choosing a good epsilon can be done using careful floating-point precision analysis, or it can be done by just throwing values at the wall and seeing what sticks. Needless to say, most code-and-burn game programmers choose the second method.

If your values are in the "1.0" range (i e, measured in meters) then 1e-5 is a good value for epsilon, because it's about one bit's worth of the mantissa at scale 1.0 (very loosely). If you're working with inches instead of meters, you might want 1e-4 instead -- or, if you're really sloppy, 1e-3.

Burn, baby, burn!

##### Share on other sites
alright, I'm still getting the same problem. this time I've got this code:

#define EPSILON (1e-5)typedef enum pointPos {PLANE_FRONT, PLANE_BACK, PLANE_COINCIDE} pointPos;/** test whether or not a point is in front, behind, or coincides with a plane **/pointPos classifyPoint(FACE *face, Vertex3 *point){  float p = scalarProduct(&face->normal, point) + face->distance;  if((p > -EPSILON) && (p < EPSILON)) return PLANE_COINCIDE;  if( p < 0.0f ) return PLANE_BACK;  if( p > 0.0f ) return PLANE_FRONT;}

the first vertex that it thinks is wrong (which is right) is this, along with the face normal and distance:

point checking for: (2,2,-2)
face distance: 2
face normal: (0, 1, 0)

my epsilon not sufficient? I've tried 1e-5, 1e-4, and 1e-3.

(1e-5 == 0.00001), correct?

##### Share on other sites
Usually, if I don't understand what happens, I add more printf():s to see what's happening. You could print the values of your variables out before comparing them. Then, if you are lucky, you could see something that starts to make sense.

For example there you have:

point checking for: (2,2,-2)
face distance: 2
face normal: (0, 1, 0)

If I'm not calculating wrong, your p is going to be
p = 4;
not p = 0;

So it's not even close to zero in that case.

##### Share on other sites
alright, all the math is correct, at least for the classifyPoint() Fucntion. I'm assuming my functions for getting the normaland distance of a plane are correct, because if I just skip trying to determine if all the vertices are not outside the plane, I can successfully draw a cube (or many) on the screen and have it completely put together after fidning all the missing vertices and then putting them in the correct order. what could be wrong here? I'm stumped.

I'm pretty sure all these functions are correct:

/** return the normal of a face **/Vertex3 getNormal(FACE *face){  Vertex3 U, V, normal;  // subtractVV subtracts two vertexes (arg2 from arg1)  U = subtractVV(&face->vertex[1], &face->vertex[0]);  V = subtractVV(&face->vertex[2], &face->vertex[1]);  normal = vectorialProduct(&U, &V);  return normal;}/** normalize a vector **/int normalize(Vertex3 *normal){  double length;  length = (float)sqrt(pwr(normal->x, 2) +                       pwr(normal->y, 2) +                       pwr(normal->z, 2));  if (length != 0)  {    normal->x = (float)(normal->x / length);    normal->y = (float)(normal->y / length);    normal->z = (float)(normal->z / length);  }  return 0;}/** return the distance of a plane **/float getDistance(FACE *face){  return (float)scalarProduct(&face->normal, &face->vertex[0]);}

##### Share on other sites
I think this is the problem: are there two different distance formulas? as in, theres a distance between a plane and its origin, and isn't there a separate distance required for this such as the distance bewteen a given vertex and the origin? ...

Edit:

distance between a plane and the origin, and length of a vector.

perhaps length of a vector is what I'm supposd to use here...

Edit: nope. thats not it. all my calculations seem to work just fine until I try to classifyPoint();

any input on this would be great.

[Edited by - LabRat404 on November 29, 2004 9:58:08 PM]

##### Share on other sites
You're not actually normalizing the face normal when you calculate it. You have to do that before you return it.

Also, sometimes a plane equation is written as Ax+By+Cz+D = 0, sometimes it's Ax+By+Cz = D -- note the difference in sign. Make sure you use the same convention throughout your code.

If you step through the entire function, and look at all the values that come out, you should easily be able to tell what is going wrong.

##### Share on other sites
all the normals I calculate get normalized right after they are calculated. is that what you mean? that a normalized normal is not always what I need?

Edit: as soon as I get the normal, it gets normalized directly afterward, as shown:
...world->brush[g].face.normal = getNormal(&world->brush[g].face); /* get the plane's normal */      normalize(&world->brush[g].face.normal); /* normalize the normal */...

my normalize function is this:

/** normalize a normal **/int normalize(Vertex3 *normal){  double length=getLength(normal);  if (length != 0)  {    normal->x = (float)(normal->x / length);    normal->y = (float)(normal->y / length);    normal->z = (float)(normal->z / length);  }  return 0;}/** return the length of a vector **/double getLength(Vertex3 *vector){  return (double)sqrt(pwr(vector->x, 2) +                      pwr(vector->y, 2) +                      pwr(vector->z, 2));}