Skip to main content
gamedev.net
🔒 Locked

Cube normals

Started by Endar 5 replies 1.3k views
Original Post
Endar
Endar
I've got a cube with its points:

(-0.5f,  0.5f,  0.5f)
(-0.5f, -0.5f,  0.5f)
( 0.5f,  0.5f,  0.5f)
( 0.5f, -0.5f,  0.5f)
( 0.5f, -0.5f, -0.5f)
( 0.5f,  0.5f, -0.5f)
(-0.5f,  0.5f, -0.5f)
(-0.5f, -0.5f, -0.5f)

And I put its normals in the same spots, because the normals are defined per-vertex. Is this the right way so it can be seen whichever vertices are rotated and pointing at the camera? So we can see all three sides?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Illco
Illco
Well in a cube each vertex is used three times -- once for each side of the cube. Each use, in this sense, requires a different normal. So if you want per vertex normals in a cube you will need 24 vertices instead of eight. The positions will be repeated.

Illco
Endar
Endar
Really? Well, I called it per-vertex because I'm using vertex arrays in OGL.

class CVertex3d{       CVector3d pos;       CVector3d normal;       float u,             v;       CColor color;};


That's my vertex class.

When you say that each vertex is used three times, once for every side of the cube, do you mean that its processed 3 times? Because I thought that vertex arrays were supposed to stop that.

Or am I misunderstanding?
[size="2"][size=2]Mort, Duke of Sto Helit: NON TIMETIS MESSOR -- Don't Fear The Reaper
Metus
Metus
one normal per vertex perpendicular to the current face will result in a flat-shaded cube and for that, 36 normals are waay overhead - if you're up for a flat-shaded cube, you can use a per-face normal.


What i recommend is to create a cube using 8 vertices, 8 normals (not perpendicular to any xyz plane) and an indexbuffer
Ethereal
Enigma
Enigma
If you want flat shading you either have to specify each unique vertex (vertex meaning position and normal), resulting in 24 vertices:
GLfloat const positions[] ={	-0.5, 0.5, 0.5,	-0.5, 0.5, 0.5,	-0.5, 0.5, 0.5,	-0.5, -0.5, 0.5,	-0.5, -0.5, 0.5,	-0.5, -0.5, 0.5,	0.5, 0.5, 0.5,	0.5, 0.5, 0.5,	0.5, 0.5, 0.5,	0.5, -0.5, 0.5,	0.5, -0.5, 0.5,	0.5, -0.5, 0.5,	0.5, -0.5, -0.5,	0.5, -0.5, -0.5,	0.5, -0.5, -0.5,	0.5, 0.5, -0.5,	0.5, 0.5, -0.5,	0.5, 0.5, -0.5,	-0.5, 0.5, -0.5,	-0.5, 0.5, -0.5,	-0.5, 0.5, -0.5,	-0.5, -0.5, -0.5,	-0.5, -0.5, -0.5,	-0.5, -0.5, -0.5};GLfloat const normals[] ={	-1, 0, 0,	0, 1, 0,	0, 0, 1,	-1, 0, 0,	0, -1, 0,	0, 0, 1,	1, 0, 0,	0, 1, 0,	0, 0, 1,	1, 0, 0,	0, -1, 0,	0, 0, 1,	1, 0, 0,	0, -1, 0,	0, 0, -1,	1, 0, 0,	0, 1, 0,	0, 0, -1,	-1, 0, 0,	0, 1, 0,	0, 0, -1,	-1, 0, 0,	0, -1, 0,	0, 0, -1};GLubyte const indices[] ={	0, 3, 21, 18,	4, 10, 13, 22,	2, 8, 11, 5,	6, 15, 12, 9,	1, 19, 16, 7,	14, 17, 20, 23};

or you can take advantage of that fact that as long as you are drawing quads each face has more vertices than each vertex has faces and that under flat shading mode OpenGL should use the last specified vertex attribute for the entire face. In this case you should be able to use:
GLfloat const positions[] ={	-0.5, 0.5, 0.5,	-0.5, -0.5, 0.5,	0.5, 0.5, 0.5,	0.5, -0.5, 0.5,	0.5, -0.5, -0.5,	0.5, 0.5, -0.5,	-0.5, 0.5, -0.5,	-0.5, -0.5, -0.5,};GLfloat const normals[] ={	0, 0, 0, // doesn't matter	0, 0, 1,	0, 1, 0,	1, 0, 0,	0, 0, -1,	0, 0, 0, // doesn't matter	-1, 0, 0,	0, -1, 0};GLubyte const indices[] ={	0, 1, 7, 6,	1, 3, 4, 7,	0, 2, 3, 1,	2, 5, 4, 3,	0, 6, 5, 2,	5, 6, 7, 4};

Disclaimer: neither of these are tested!

Enigma
deavik
deavik
Endar,

The thing is that if you only have the vertices declared, the polygons may be triangles, squares, whatever. You need some separate information telling you which vertices make up which polygons, like an index ^^^. Most 3d export formats take care of that. Now,

1. As you are reading in the faces, calculate face normals by doing a cross product of the vectors making up 2 sides of the polygon. Each model format has a anticlockwise or clockwise arrangement of vertices for each poly, check that out so you get the correct direction for the cross product.

2. Add the face normal to that of each vertex making up the polygon (CVector3D normal in your class).

3. Normalize the vertex normals looping through each vertex so that they have unit length.

And you're done! This way you have averaged out vertex normals - called smooth normals. Turn on smooth shading in opengl (glShadeModel), and sample the spectacular results! Have fun!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.