Surface Normal Calculation

After looking around this code should be able to calculate the normals for triangles/quads however I seem to be getting the wrong answer. (As I am getting 4 which shouldn't be possible).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
float* CrossProduct(float *a, float *b)
{
	float Product[3];

        //Cross product formula 
	Product[0] = (a[1] * b[2]) - (a[2] * b[1]);
	Product[1] = (a[2] * b[0]) - (a[0] * b[2]);
	Product[2] = (a[0] * b[1]) - (a[1] * b[0]);

	return Product;
}

void Function()
{
	float Vector[3], Vector2[3];

	//3 points of a quad
	float v1[] = {1,  -1, -1};
	float v2[] = {1,  -1,  1};
	float v3[] = {-1, -1,  1};
        //float v4[] = {-1, -1, -1};

	Vector[0] = v3[0] - v1[0];
	Vector[1] = v3[1] - v1[1];
	Vector[2] = v3[2] - v1[2];

	Vector2[0] = v2[0] - v1[0];
	Vector2[1] = v2[1] - v1[1];
	Vector2[2] = v2[2] - v1[2];

	float *Normal = CrossProduct(Vector,Vector2);
	//Normal should be 0,-1,0 but turns out as 0,4,0
}


Am I just making a simple math error somewhere? Any help is appreciated.
You're doing it right you just need to normalize the resulting normal.

Here's my code for computing surface normal of a plane given three points:

1
2
3
4
5
6
7
8
9
10
11
void PlaneEntity::computePlane(vector3 A, vector3 B, vector3 C)
{
    vector3 N = (A - B) % (B - C); //perform cross product of two lines on plane

    if(N.getMagnitude() > 0)
    {
        N.normalize();  //normalize
        m_n = N;         //assign new normal to member normal
        m_d = n * A;   //offset plane from origin
    }
}


Normalize:
1
2
3
4
5
6
7
8
void vector3::normalize(){

    double length = sqrt(x*x+y*y+z*z);

    x = x/length;
    y = y/length;
    z = z/length;
}
Last edited on
You forgot to tell him about your overloaded '%'
Last edited on
But, that's the thing... It's magic! harhar, jk.

% - cross product overload
1
2
3
4
5
6
vector3 vector3::operator%(const vector3 &rhs)
{
    return vector3(y*rhs.z - z*rhs.y, 
                   z*rhs.x - x*rhs.z, 
                   x*rhs.y - y*rhs.x);
}


Thanks, ToniAz.
Last edited on
Normal should be 0,-1,0 but turns out as 0,4,0
The reason that you get a wrong result is because you return a pointer to local variable, that's wrong in any cases
The reason that you get a wrong result is because you return a pointer to local variable, that's wrong in any cases

Yeah I rewrote that part a little while ago as it didn't look like a good idea, thanks.

I thought that '%' was a secret way to do cross products for a second there lol. Thanks for the help, do you mind explaining exactly why it needs to be normalized for it to work correctly and why that particular formula?
@coder777

The result he's getting is correct. I ran his code and came up with the same answer. He just needs to perfom the normalize function on the answer to get the correct Normal.

He's also initilizing the local float pointer with an array of floats. I don't see how that could be wrong if it's right... It's just not normal.
Well a normal is essentially a direction in either 2D or 3D space. Normals are awesome because you can find which way an enemy is facing and normalize that direction and then scale the normal by a scalar value, say 'speed', and they'll go off in that direction with a scaled normal which is then considered their velocity.

The reason that formula is because a Normal is defined by: A vector whose magnitude is equal to one and x, y and z's are less than 1 and greater than 0.

It comes down to simple math.

double length = sqrt(x*x+y*y+z*z);

That's the same formula as the pythagorean theorem a^2+b^2+z^2 = c^2

After you've calculated the length, or the 'Magnitude' of this vector you divide it's parts by this length to normalize them between 0 and 1

1
2
3
x = x/length;
y = y/length;
z = z/length;


That'll give you the x, y and z values who's magnitude is exactly 1. To break down the scaling part think about this:

assume the values x, y, z are normalized
1
2
3
4
5
scale = 10;

x * scale;
y * scale;
z * scale;

the magnitude of this vector will be 10 and its compnents scaled appropriately to make it possible.

I wish I had time to illustrate by drawing a picture. But, I'm currently pulling an all nighter to study for finals :/
Last edited on
@Anthony Hernandez
I'm not saying anything about his calculation. All I'm saying is that returning a pointer to local variable is wrong in any case.

The reason is that all local variables are discarded as soon as the function exits. It is undefined what you get after this.

One more thing: Why do you overload the operator%? Why not simply call it cross_product() (or similar?
Right now I have all the operators overloaded in my vector3 for AI, physics and graphics and I never really used the % for anything. So it's more of a "why not" design on my part :P

I think it's the only non-intuitive operator I have implemented atm.
@Anthony Hernandez: a normal (orthogonal) does not need to be normalized (unity), and the magnitud (area) may be important.
Thanks for the explanation Anthony, hopefully I will be able to do some cool things with normals once I learn more about them.

It looks like normalizing got the answer I was looking for, now to see if I can get this sphere-plane collision working (I will probably end up back here :P).
If you need help with collisions I have most of them for both RigidBodies and Particals C:
I have a feeling the math part of it is going to hurt me more than anything right now, I probably need to look up some more stuff on vector related material. But I will take any help I can get :D.
Topic archived. No new replies allowed.