Jump to content

  • Log In with Google      Sign In   
  • Create Account

calculating normals for triangle strip model, not terrain


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 juddo   Members   -  Reputation: 132

Like
1Likes
Like

Posted 07 November 2012 - 08:44 PM

hello all,

i am reading vertex data from a game file that stores a character model in triangle strips (ps2 game, hence why triangle strips are used). i did concider converting the triangle strips into vertex indexing to help ease the pain of calculating my normals at runtime, but still would like some help calculating normals for triangle strips.

i recently read on here that triangle strips flip cw/ccw culling every triangle if backface culling is on. below is my code for calculating normals at the moment;

[source lang="cpp"] float vu[3]; float vv[3]; float cp[3]; float result; for (int k = 0; k < nvertices; k++) { vu[0] = vertices[k + 1][0] - vertices[k][0]; vu[1] = vertices[k + 1][1] - vertices[k][1]; vu[2] = vertices[k + 1][2] - vertices[k][2]; vv[0] = vertices[k + 1][0] - vertices[k + 2][0]; vv[1] = vertices[k + 1][1] - vertices[k + 2][1]; vv[2] = vertices[k + 1][2] - vertices[k + 2][2]; cp[0] = (vu[2] * vv[1]) - (vu[1] * vv[2]); cp[1] = (vu[0] * vv[2]) - (vu[2] * vv[0]); cp[2] = (vu[1] * vv[0]) - (vu[0] * vv[1]); result = (float)sqrt((cp[0]*cp[0]) + (cp[1]*cp[1]) + (cp[2]*cp[2])); if (result == 0.0f) result = 1.0f; normals[k][0] = cp[0] / result; normals[k][1] = cp[1] / result; normals[k][2] = cp[2] / result; }[/source]

when i run my program with the above code, i see the following;

Posted Image

&&

Posted Image

you can see on this side shot that i can see through the model (less than desireable.) at the moment i am iterating through every vertex, do i need an offset in my loop to calculate the next triangle or next vertex? it looks like the normals are facing away from each other...

and this is the drawing code...

[source lang="cpp"]glPushMatrix(); glTranslatef(posx_, posy_, posz_); glRotatef(90.0f, 0, 0, 1); glRotatef(turnrate_, 1, 0, 0); glBegin(GL_TRIANGLE_STRIP); for (int i = 0; i < model_.nvertices; i++) { glNormal3f(model_.normals[i][0], model_.normals[i][1], model_.normals[i][2]); glVertex3f(model_.vertices[i][0], model_.vertices[i][1], model_.vertices[i][2]); } glEnd();glPopMatrix();[/source]


thanks for your time,


best regards,

justin

Edited by juddo, 07 November 2012 - 09:25 PM.


Sponsor:

#2 Lauris Kaplinski   Members   -  Reputation: 841

Like
2Likes
Like

Posted 08 November 2012 - 02:09 AM

  • You should not iterate from 0 to nvertices - 1, but instead either from 0 to nvertices - 3, or 2 to nvertices - 1. For example try to analyze what happens, if i = nvertices - 1 in your cycle.
  • You have to flip the direction of calculated normal each step. This is beacuse the order of triangle vertices alternates between CW/CCW while triangle strip is used. This seems to be the problem why you are having wrong normals.
A segment of triangle strip - notice how the first triangle should be 123 and second 324 to be CW
Posted Image
Lauris Kaplinski

First technology demo of my game Shinya is out: http://lauris.kaplinski.com/shinya
Khayyam 3D - a freeware poser and scene builder application: http://khayyam.kaplinski.com/

#3 mhagain   Crossbones+   -  Reputation: 8279

Like
2Likes
Like

Posted 08 November 2012 - 04:55 AM

  • You should not iterate from 0 to nvertices - 1, but instead either from 0 to nvertices - 3, or 2 to nvertices - 1. For example try to analyze what happens, if i = nvertices - 1 in your cycle.


This answer is correct but I need to point out that this is an inclusive range, so the actual loop will be "for (k = 0; k < nvertices - 2; k++)" or "for (k = 2; k < nvertices; k++)".

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#4 juddo   Members   -  Reputation: 132

Like
1Likes
Like

Posted 08 November 2012 - 06:18 AM

thank you both for the replys. i think i know what i need to do, just not sure what order i need to read my vu and vv variables when alternating?

so to clarify for myself... for the first alternating read, what vertices do i want vu and vv to be? vu is 2-3? vv is 2-0? what about the second alternating read? vu is ?-? and vv is ?-? does the cross product also change on each alternating read? or just the vertices i read into vu and vv? i thought i had this in concrete, but the more sample code on calculating normals i find, the more confused i become. every source code calculating normals i find reads the vertices in a different order... i've now changed my vu vv and cross product dozens of times...!

correct me if i am wrong, going by the diagram the first read is vertex 1, 2 then 3. and the second read is 3, 4 then 2? cw then alternate ccw?

[source lang="cpp"]if (flip > 0) { flip = 0; vu[0] = vertices[1][x] - vertices[2][x]; vu[1] = vertices[1][y] - vertices[2][y]; vu[2] = vertices[1][z] - vertices[2][z]; vv[0] = vertices[1][x] - vertices[0][x]; vv[1] = vertices[1][y] - vertices[0][y]; vv[2] = vertices[1][z] - vertices[0][z];}else { flip = 1; vu[0] = vertices[?][x] - vertices[?][x]; vu[1] = vertices[?][y] - vertices[?][y]; vu[2] = vertices[?][z] - vertices[?][z]; vv[0] = vertices[?][x] - vertices[?][x]; vv[1] = vertices[?][y] - vertices[?][y]; vv[2] = vertices[?][z] - vertices[?][z];}[/source]

Edited by juddo, 08 November 2012 - 06:26 AM.


#5 Lauris Kaplinski   Members   -  Reputation: 841

Like
1Likes
Like

Posted 08 November 2012 - 09:14 AM

Do it the easier way:

	...
	vu[0] = vertices[k + 1][0] - vertices[k][0];
	vu[1] = vertices[k + 1][1] - vertices[k][1];
	vu[2] = vertices[k + 1][2] - vertices[k][2];

	vv[0] = vertices[k + 2][0] - vertices[k][0];
	vv[1] = vertices[k + 2][1] - vertices[k][1];
	vv[2] = vertices[k + 2][2] - vertices[k][2];

	... Now calculate your normals from vu and vv ...

	if (k & 1) {
		// Invert normal for all even triangles
		normals[k][0] = -normals[k][0];
		normals[k][1] = -normals[k][1];
		normals[k][2] = -normals[k][2];
	}

I.e. just invert the normal. You probably have to test by trial and error, whether you have to invert normal for even or odd triangles because it depends on which convention is used by model format.
Lauris Kaplinski

First technology demo of my game Shinya is out: http://lauris.kaplinski.com/shinya
Khayyam 3D - a freeware poser and scene builder application: http://khayyam.kaplinski.com/

#6 juddo   Members   -  Reputation: 132

Like
0Likes
Like

Posted 08 November 2012 - 07:07 PM

thank you Lauris Kaplinski for the great reply!

i did as you mentioned and have a better result, just not the right one. i tried changing odd to even and (k & 1) is the only one that gives near results. i've taken a screenshot to show what i see...

Posted Image

&&

Posted Image

i can see through the mesh which i hope is a result of incorrect normals, or else something in my rendering section is broken!

[source lang="cpp"] float vu[3]; float vv[3]; float cp[3]; float result; for (int k = 0; k < nvertices - 2; k++) { vu[0] = vertices[k + 1][0] - vertices[k][0]; vu[1] = vertices[k + 1][1] - vertices[k][1]; vu[2] = vertices[k + 1][2] - vertices[k][2]; vv[0] = vertices[k + 2][0] - vertices[k][0]; vv[1] = vertices[k + 2][1] - vertices[k][1]; vv[2] = vertices[k + 2][2] - vertices[k][2]; cp[0] = (vu[1] * vv[2]) - (vu[2] * vv[1]); cp[1] = (vu[2] * vv[0]) - (vu[0] * vv[2]); cp[2] = (vu[0] * vv[1]) - (vu[1] * vv[0]); result = (float)sqrt((cp[0]*cp[0]) + (cp[1]*cp[1]) + (cp[2]*cp[2])); if (result == 0.0f) result = 1.0f; normals[k][0] = cp[0] / result; normals[k][1] = cp[1] / result; normals[k][2] = cp[2] / result; if (k &amp;amp; 1) { normals[k][0] = -normals[k][0]; normals[k][1] = -normals[k][1]; normals[k][2] = -normals[k][2]; } }[/source]

above i changed the cross product from what i had originally. a few articles i read on calculating normals seem to use the same cross product. i hope its not incorrect. changing it gives me a completely dark shaded model.

*scratches head* Posted Image

Edited by juddo, 08 November 2012 - 07:25 PM.


#7 Lauris Kaplinski   Members   -  Reputation: 841

Like
0Likes
Like

Posted 09 November 2012 - 02:19 AM

Oops, I think I got the problem. As of now, you are calculating normals for all vertices except the last two. Your model is actually composed of short triangle strips and for each strip the last vertices do not have correct normals.

You can set the last two vertices the same as the preceding one because they are part of the same triangle:
for (int k = nvertices - 2; k < nvertices; k++) {
	for (int i = 0; i < 3; i++) normals[k][i] = normals[nvertices - 3][i];
}

But this whole calculation is still wrong because you are not averaging normals of neighboring triangles. Thus each vertex gets normal calculated only from one of the triangles it is part of - and thus you will get sharp edges.
To do proper normal calculation there should be some meta-information in model file - like smoothing groups. Otherwise you could make completely smooth model, that probably does not look right.
Lauris Kaplinski

First technology demo of my game Shinya is out: http://lauris.kaplinski.com/shinya
Khayyam 3D - a freeware poser and scene builder application: http://khayyam.kaplinski.com/




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS