#### Archived

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

# Precaculating face and vertex normals?

## Recommended Posts

ByteMe95    122
I''m trying to speed up my 3d demo. I could make it MUUUCH faster by NOT calculating the vertex normals every frame (I know i shouldn''t do it but i wanted my demo to work already and put it aside for now) Anyway, when I load in the asc file I calculate all face normals and vertex normals. Now I figured when i transform my vertices, if I apply the same transformation matrix to my face normals and vertex normals they should be calculated correctly and then I would be able to use them But for some reason that doesnt work. The lighting looks like it''s rotating with the faces (so on a sphere, it would start with the light shining right on it, but as it rotates the light rotates with it like it''s part of the object). I think that''s what was happening when i tried that, I dont really remember. Just wanted to know if that''s the way "it''s done" and if it''s posssible to precomupte everything and then just rotate the normals with everything else Thanks ByteMe95::~ByteMe95()

##### Share on other sites
shmaLbus    122
hmm, it should work just fine, calculating the normals all the time can get expensive.

if it looks like the light is being rotated with the object then the problem sounds like when you rotate the object, you aren''t rotating the normals also. that definatly sounds like the problem, you should just be able to apply the exact same transformation to the precalculated normal as its owner then just recalc the lighting each rotation.

i''d have a look at your code that rotates the normal or the code that calculates the lighting each frame if i were you.

-werdup-

##### Share on other sites
mossmoss    326
quote:
Original post by ByteMe95
Anyway, when I load in the asc file I calculate all face normals and vertex normals. Now I figured when i transform my vertices, if I apply the same transformation matrix to my face normals and vertex normals they should be calculated correctly and then I would be able to use them.

Almost... If your transformation is only rotation, it should work. But if it includes translation and scaling, you'll have problems.

To handle translation, simply don't apply it. Remember that your normals are relative offsets, not absolute positions (like your vertices). Being relative, you don't translate them.

Rotate the normals same as you rotate your vertices.

As for scaling, I don't exactly remember. You'll need to look this one up... it's not exactly straightforward if you have non-uniform scaling. Although most people avoid that in their transforms anyhow...

To summarize: you have a matrix M = |Rt| , a vertex v and a normal n . You would do:

  v' = Rv + t n' = Rn

---- --- -- -
Blue programmer needs food badly. Blue programmer is about to die!

Edited by - mossmoss on July 24, 2000 12:47:42 PM

##### Share on other sites
ByteMe95    122
I dony have my code on me at the moment, but the transformation goes prettymuch something like this:

  Object3D::ApplyTransformations(){ 3DV Temp; for(int i=0; i; VEC_MultMatrix(&Temp, TransformMX, &Vertices[i]); Temp = VNormals[i]; //Vertex normals VEC_MultMatrix(&Temp, TransformMX, &VNormals[i]); } for(i=0; i

Where Vec.. is defined
void VEC_MultMatrix(3DV *Source, Matrix mx, 3DV *Dest);

I dont think there''s a problem with that function cause it rotates the object just fine.

Any ideas?

ByteMe95::~ByteMe95()

##### Share on other sites
shmaLbus    122
well unless i'm mistaken his demo was just something rotating so i knew that's not his problem
i am assuming you're not? what's your code for generating 'TransformMX'?

Edited by - shmaLbus on July 24, 2000 8:27:25 PM

##### Share on other sites
ByteMe95    122
I only call Test.Rotate(1, 2, 3) at initialization, and this is what it calls:

  void Object3D::Rotate(float ax, float ay, float az){ Matrix xmat, ymat, zmat, mat1, mat2; IdentityMatrix(mat1); IdentityMatrix(mat2); xmat[0][0]=1; xmat[0][1]=0; xmat[0][2]=0; xmat[0][3]=0; xmat[1][0]=0; xmat[1][1]=cos(ax); xmat[1][2]=sin(ax); xmat[1][3]=0; xmat[2][0]=0; xmat[2][1]=-sin(ax); xmat[2][2]=cos(ax); xmat[2][3]=0; xmat[3][0]=0; xmat[3][1]=0; xmat[3][2]=0; xmat[3][3]=1; ymat[0][0]=cos(ay); ymat[0][1]=0; ymat[0][2]=-sin(ay); ymat[0][3]=0; ymat[1][0]=0; ymat[1][1]=1; ymat[1][2]=0; ymat[1][3]=0; ymat[2][0]=sin(ay); ymat[2][1]=0; ymat[2][2]=cos(ay); ymat[2][3]=0; ymat[3][0]=0; ymat[3][1]=0; ymat[3][2]=0; ymat[3][3]=1; zmat[0][0]=cos(az); zmat[0][1]=sin(az); zmat[0][2]=0; zmat[0][3]=0; zmat[1][0]=-sin(az); zmat[1][1]=cos(az); zmat[1][2]=0; zmat[1][3]=0; zmat[2][0]=0; zmat[2][1]=0; zmat[2][2]=1; zmat[2][3]=0; zmat[3][0]=0; zmat[3][1]=0; zmat[3][2]=0; zmat[3][3]=1; MatrixMult(TransformMX,ymat,mat1); MatrixMult(mat1,xmat,mat2); MatrixMult(mat2,zmat,TransformMX);} `

with MatrixMult(mat1, mat2, destination_matrix)

and that''s it
I dont get it, I''ve tried many times. If i take out calculating the vertexnormals my fps goes from 40 to 60
Gotta get it out!!!

ByteMe95::~ByteMe95()

##### Share on other sites
phueppl1    122
quote:

As for scaling, I don't exactly remember. You'll need to look this one up... it's not exactly straightforward if you have non-uniform scaling. Although most people avoid that in their transforms anyhow...

the normals are for the lightning, right?
i though u'd have to give normals with the length of 1?
so, you'd just don't scale your normal either, oder?
I'm still pretty new, but i think i read something like that...

cya,

Phil

Edited by - phueppl1 on July 24, 2000 12:42:41 AM

##### Share on other sites
ByteMe95    122
The only transformation I''m doing as of right now is rotation, so scaling and translation have nothing to do with this problem.

I have no idea what the problem is, anyone got a clue?
When I rotate it the lighting doesnt go completely crazy with crazy colors, it still looks like a shaded torus, but the light moves around funny, it doesnt stay in one place like it''s shining at the torus and torus is rotating, like the demo.

In that code snippet of rotating the vertices and vertex normals I also tried to put in VNormals = Normalize(VNormals[i]);
That didnt help either

This thing is driving me nuts, i just want to get it right and be done with it!!

- ROb

ByteMe95::~ByteMe95()

##### Share on other sites
Guest Anonymous Poster
Have you tried drawing in the normals every frame to see if they''re rotating correctly?

In fact, this doesn''t sound like a problem with your normals at all, but with your lighting. This is exactly what would happen if you were to prelight your object. Are you sure that the lighting is being recalculated every frame?

##### Share on other sites
Guest Anonymous Poster
One other thing - Have you considered doing your lighting in object space instead of world space? Instead of transforming all of your object normals by the object''s world matrix, you can just transform your lights by the inverse of this matrix. Depending upon the number of lights in your scene, this will probably be much faster.

##### Share on other sites
ByteMe95    122
I''m still a little confused as to world space and obejct space. I mean I understand exactly what the difference is and all, but I dont understand the world matrix.

Right now my Object3D class has world coordinates:
3DV WorldCoord;

And you can set it to say 50,30,-300

And then all i do is when i project my polys (not using a matrix either, just calculations) i subtract the worldcoord from the xyz of the poly and then project, so I just add in 3 subtractions for my projection.

And I''m pretty sure my lighting algorithm works fine, have you seen my demo?
If I calculate the vertex normals every frame the lighting is flawless, looks just as it should. But if i precompute and try to rotate them, then it doesn''t work. And yes my lighting is recomputed every frame.

I dont know about drawing the normals, i dont want to get into programming that for no reason. I''m thinking there is a simple answer im missing.

ByteMe95::~ByteMe95()

##### Share on other sites
Julio    116
if your world (scene, whatever) is dynamic then you''ll probably have to recalculate every frame. if it''s static then you could use a look-up table type system.

JoeMont001@aol.com www.polarisoft.n3.net

##### Share on other sites
Guest Anonymous Poster
The world matrix is just a way of placing and orientating your object in the scene. You said in one of your earlier mails that you were rotating your object. Presumably you doing this by transforming your object vertices by a matrix - this matrix is your world matrix.

I thing the only way to see what is happening is to display your normals - this is fairly easy in D3D (is that what you''re using?) and a piece of code like this will definitely come in useful in the future (I''ve used this many times!)

##### Share on other sites
ByteMe95    122
I''m not using d3d or any API, this is all 100% software, so I''d rather not take the time to do that, unless you have some code that could do it already

And are you saying my world matrix is my transformation matrix?

Can someone clarify something for me.
How many separate matrices should one object have? Right now i just have one, and when u call a transformation it multiplies that transofmration by the current matrix
so lets say Object.Translate(2, 2, -2) fills in the matrix with a translation and then Object.Rotate(.1, .1, .1) will multiply the rotation matrix for those values by the translation matrix alread filled, giving you the final transformation matrix.

Then I loop through all vertices and multiply them by that final matrix.
Then "Object->World", I do
(Object.)x+=WorldCoord.x
y+=Worldcoord.y;
z+=worldcoord.z

then peform the projection
screen_x = x/z; //abbreviated form
screen_y = y/z;

and then i call my poly filler

So the only matrices i actually use are the transformations. I have no world matrix or camera matrix or anything like that, mostly because i dont fully understand them. :o)

ByteMe95::~ByteMe95()

##### Share on other sites
Guest Anonymous Poster
Yes, this transformation matrix is usually called your object''s world matrix. An individual object can only have one world matrix, but each different object in your scene can have it''s own world matrix.

The reason for calling it the world matrix is because it maps vertices from object space (i.e. relative to the object''s origin) to world space (relative to the world''s origin).

What I was suggesting earlier was that there is no need to transform all of your normals every frame. Your normals will be precalculated based on your object vertices (i.e. in object space). Instead of using your transformation matrix to transform them into world space, you could transform your light into object space and do the lighting there.

This is done by transforming your light vector and position by the inverse of the object''s world matrix. You can then do your lighting in object space, which would give the same results, but save a lot of calculation.

You may also find that the problem you have at the moment just dissapears ...

##### Share on other sites
ByteMe95    122
I''ll try to get the light rotating in obhject space instead of rotating the vertex normals. Are you sure this works??? Just want to be sure this is a viable answer before i go into coding it

ByteMe95::~ByteMe95()

##### Share on other sites
Guest Anonymous Poster
Yep - it''s the usual way of doing things.

##### Share on other sites
ByteMe95    122
I tried doing that rotating light thing, I actually like the idea.
IT doesnt fully work for me though. It seems to wokr for half of the rotation, and the object is nearly black the other half.
I tried using the inverse matrix too (which is reversing the columns and rows right?) for the light rotation, that didnt help but it was closer.

I have an updated exe and my most relevant code in a zip file.

3DTEST

Can someone please look at the exe and look at the code, maybe see what''s wrong? This way of doing lighting took my fps from 40 to ~65fps

I like it
:o)

ByteMe95::~ByteMe95()