Archived

This topic is now archived and is closed to further replies.

Calculating Normals

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Can anyone explain the math to calculate the normal of a triangle? I have asked this before in another forum but they all said somthing different! lol I know it has to do with selecting any 2 vertices and doing the crosproduct, but... im not fully sure... can someone explain it?

Share this post


Link to post
Share on other sites
if you have 3 points that make up the triangle, when you subtract any point from any other you will get a vector along the plane of that triangle. the cross product of these 2 vectors will give you the normal.
example:
vector1 = vertex2-vertex1
vector2 = vertex3-vertex1
normal = cross(vector1, vector2)
then you probably want to normalize this vector

Share this post


Link to post
Share on other sites
make 2 vectors by substract two pairs of vertices, and then cross them.

Share this post


Link to post
Share on other sites
This is my code, but i get really crappy looking faces and some are just black! the math all looks fine to me! please help!

(note: faces are drawn clockwise!)


for(i = 0; i < h1.num_faces; i++)
{

float v1x = frames[j].vertices[frames[j].faces[i].vertexindices[2]].x - frames[j].vertices[frames[j].faces[i].vertexindices[0]].x;
float v1y = frames[j].vertices[frames[j].faces[i].vertexindices[2]].y - frames[j].vertices[frames[j].faces[i].vertexindices[0]].y;
float v1z = frames[j].vertices[frames[j].faces[i].vertexindices[2]].z - frames[j].vertices[frames[j].faces[i].vertexindices[0]].z;

float v2x = frames[j].vertices[frames[j].faces[i].vertexindices[1]].x - frames[j].vertices[frames[j].faces[i].vertexindices[2]].x;
float v2y = frames[j].vertices[frames[j].faces[i].vertexindices[1]].y - frames[j].vertices[frames[j].faces[i].vertexindices[2]].y;
float v2z = frames[j].vertices[frames[j].faces[i].vertexindices[1]].z - frames[j].vertices[frames[j].faces[i].vertexindices[2]].z;


frames[j].faces[i].normalx = v2y*v1z - v2z*v1y;
frames[j].faces[i].normaly = v2z*v1x - v2x*v1z;
frames[j].faces[i].normalz = v2x*v1y - v2y*v1x;
}

Share this post


Link to post
Share on other sites
Hey,

You have to normalize the normal:



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

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The order of the vertices in the triangle also matters! The counterclockwise crossproduct of 2 vectors will give the normal in a right-handed system and the opposite in a left-handed system.

if your vertices 0,1,2 are in counter-clockwise order then
(v[1] - v[0]) x (v[2] - v[0]) will give you your normal, otherwise it will give a normal facing the opposite direction in.

And yes, and in general you must normalize your normal afterwards.

Share this post


Link to post
Share on other sites
I get this warning...
--------------------Configuration: lesson1 - Win32 Debug--------------------
Compiling...
Lesson1.cpp
c:\documents and settings\colin\my documents\12\obj.h(251) : warning C4244: ''/='' : conversion from ''double'' to ''float'', possible loss of data
c:\documents and settings\colin\my documents\12\obj.h(252) : warning C4244: ''/='' : conversion from ''double'' to ''float'', possible loss of data
c:\documents and settings\colin\my documents\12\obj.h(253) : warning C4244: ''/='' : conversion from ''double'' to ''float'', possible loss of data

Lesson1.obj - 0 error(s), 3 warning(s)
-----------------------------------------------

and then my object is just black!


for(i = 0; i < h1.num_faces; i++)
{
float v1x = frames[j].vertices[frames[j].faces[i].vertexindices[1]].x - frames[j].vertices[frames[j].faces[i].vertexindices[0]].x;
float v1y = frames[j].vertices[frames[j].faces[i].vertexindices[1]].y - frames[j].vertices[frames[j].faces[i].vertexindices[0]].y;
float v1z = frames[j].vertices[frames[j].faces[i].vertexindices[1]].z - frames[j].vertices[frames[j].faces[i].vertexindices[0]].z;

float v2x = frames[j].vertices[frames[j].faces[i].vertexindices[2]].x - frames[j].vertices[frames[j].faces[i].vertexindices[0]].x;
float v2y = frames[j].vertices[frames[j].faces[i].vertexindices[2]].y - frames[j].vertices[frames[j].faces[i].vertexindices[0]].y;
float v2z = frames[j].vertices[frames[j].faces[i].vertexindices[2]].z - frames[j].vertices[frames[j].faces[i].vertexindices[0]].z;


frames[j].faces[i].normalx = v2y*v1z - v2z*v1y;
frames[j].faces[i].normaly = v2z*v1x - v2x*v1z;
frames[j].faces[i].normalz = v2x*v1y - v2y*v1x;

double length = sqrt( frames[j].faces[i].normalx*frames[j].faces[i].normalx + frames[j].faces[i].normaly*frames[j].faces[i].normaly + frames[j].faces[i].normalz*frames[j].faces[i].normalz );
frames[j].faces[i].normalx /= length;
frames[j].faces[i].normaly /= length;
frames[j].faces[i].normalz /= length;
}

Share this post


Link to post
Share on other sites
try: /= (float)length;

the warnings are just telling you that you are trying to assign a double to a float and there maybe some precision loss. If that not ok, just make all your normal info doubles instead of floats.

Denny

[edited by - brain21 on August 18, 2003 11:41:12 AM]

Share this post


Link to post
Share on other sites
might wanna also turn off back face drawing for now until you get the hang of it. that can lead to bleed-through or blackening out of faces

Share this post


Link to post
Share on other sites
I have a suggestion that won''t fix your problem but it will make your code a lot easier to read. Write it like this:


Frame & frame = frames[j];
for(i = 0; i < h1.num_faces; i++)
{
Face & face = frame.faces[i];
int * indices = face.vertexindices;
Vertex & vertex0 = frame.vertices[indices[0]];
Vertex & vertex1 = frame.vertices[indices[1]];
Vertex & vertex2 = frame.vertices[indices[2]];

float v1x = vertex2.x - vertex0.x;
float v1y = vertex2.y - vertex0.y;
float v1z = vertex2.z - vertex0.z;

float v2x = vertex1.x - vertex2.x;
float v2y = vertex1.y - vertex2.y;
float v2z = vertex1.z - vertex2.z;

face.normalx = v2y*v1z - v2z*v1y;
face.normaly = v2z*v1x - v2x*v1z;
face.normalz = v2x*v1y - v2y*v1x;
}

Share this post


Link to post
Share on other sites
float v1x = vertex2.x - vertex0.x;
float v1y = vertex2.y - vertex0.y;
float v1z = vertex2.z - vertex0.z;

float v2x = vertex1.x - vertex2.x;
float v2y = vertex1.y - vertex2.y;
float v2z = vertex1.z - vertex2.z;

should be

float v1x = vertex1.x - vertex0.x;
float v1y = vertex1.y - vertex0.y;
float v1z = vertex1.z - vertex0.z;

float v2x = vertex2.x - vertex0.x;
float v2y = vertex2.y - vertex0.y;
float v2z = vertex2.z - vertex0.z;

My Site

Share this post


Link to post
Share on other sites
and why don''t you make a vector class with + - / etc. operators? that way it really makes your code much more readable. Calculating the normal will be only this if you do it that way:

VECTOR3D normal = CrossProduct(vert[1] - vert[0],vert[2] - vert0]);
normal.Normalize();

My Site

Share this post


Link to post
Share on other sites