Urgent, how to render these surfaces?


I need to visualize some isosurfaces with GLUT. Since I am a beginner of opengl, I don’t want to bother studying how to do isosurface extraction from a field. I use IBM openDX to extract isosurfaces from a field (specifically, a turbulent flow field) and output the isosurfaces represented by a bouch of triangles. Then I want to see the isosurfaces approximated by the triangles with GLUT.

Now I can see those surfaces with GLUT, however, they don’t look like 3D stuff, but like some 2D stuff no matter what view point I take. I suspect that I might need to do some lighting and material setup. Can somebody give me an example doing the job. So far I don’t have to make it pretty, but need to make it work.

Thanks a lot!

Haoxiang Luo
UC San Diego

If you want lighting on, you can type these two lines into your initialisation…


The second part is that you’ll have to sepcify the normals for the triangles.

Given A triangle with vertices A,B & C. Perform a cross product between the vectors A->B & A->C. Normalise the resulting vector and plug the x,y & z into glNormal3f() before specifying the vertices.


void DrawTriangle( float x0,float y0, float z0,float x1, float y1, float z1, float x2, float y2, float z2)
float vec0[3],vec1[3],normal[3];
// calculate vectors A->B, A->C
vec0[0] = x1-x0;
vec0[1] = y1-y0;
vec0[2] = z1-z0;
vec1[0] = x2-x0;
vec1[1] = y2-y0;
vec1[2] = z2-z0;

// do cross product
normal[0] = vec0[1]*vec1[2] - vec0[2]*vec1[1];
normal[1] = vec0[2]*vec1[0] - vec0[0]*vec1[2];
normal[2] = vec0[0]*vec1[1] - vec0[1]*vec1[0];

// normalise vector
float l = sqrt( normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2] );
normal[0] /= l;
normal[1] /= l;
normal[2] /= l;

// draw triangle

This is of course the slowest lamest way of doing it… It would be better to pre-cache the normals and use display lists/vertex arrays etc for drawing…

great, it helps! thanks a lot.

now, how can I make the surface approximated by theh triangles smoother?

UC San Diego

One way to approximate the normals via the traingles is the following:
having calculated all the normals (and after setting them to the correct direction ->not inside for all the triangles “you think of drawing all the triangles, but of course you just accumulate the x/y/z parts of the normals vectors” ->example vector B is part of 6 triangles just add all the normals together and normalize them again (length 1)
this could look like this:
void averaging(void)
register unsigned long i,x;

GLfloat n[3];
for(i = 0;i < NSQ;i++)
	for(x = 0;x < NSQ;x++){
vertex_arr[i][x].nx += normals_arr[i][x][0].x;
vertex_arr[i+1][x].nx += normals_arr[i][x][0].x;
vertex_arr[i][x+1].nx +=  normals_arr[i][x][0].x;

vertex_arr[i][x].ny += normals_arr[i][x][0].y;
vertex_arr[i+1][x].ny += normals_arr[i][x][0].y;
vertex_arr[i][x+1].ny +=  normals_arr[i][x][0].y;

vertex_arr[i][x].nz += normals_arr[i][x][0].z;
vertex_arr[i+1][x].nz += normals_arr[i][x][0].z;
vertex_arr[i][x+1].nz +=  normals_arr[i][x][0].z;

vertex_arr[i+1][x].nx += normals_arr[i][x][1].x;
vertex_arr[i+1][x].ny += normals_arr[i][x][1].y;
vertex_arr[i+1][x].nz += normals_arr[i][x][1].z;

vertex_arr[i][x+1].nx += normals_arr[i][x][1].x;
vertex_arr[i][x+1].ny += normals_arr[i][x][1].y;
vertex_arr[i][x+1].nz += normals_arr[i][x][1].z;

vertex_arr[i+1][x+1].nx += normals_arr[i][x][1].x;
vertex_arr[i+1][x+1].ny += normals_arr[i][x][1].y;
vertex_arr[i+1][x+1].nz += normals_arr[i][x][1].z;
for(i = 0;i < Q;i++)
	for(x = 0;x < Q;x++)
		n[0] = vertex_arr[i][x].nx;
		n[1] = vertex_arr[i][x].ny;
		n[2] = vertex_arr[i][x].nz;
		//check_orient isn`t needed here, because all 'input' vectors had already the correct orientation 
		vertex_arr[i][x].nx = n[0];
		vertex_arr[i][x].ny = n[1];
		vertex_arr[i][x].nz = n[2];


of course it is not a perfect solution, but even with complicated surfaces you dont need ‘university math’

Hi, Tresher, slow down please. I am a beginner.

It looks to me that you are averaging the nomal vectors by considering neighbour vectors for each normal vector. But you example code is still confusing to me.

Now suppose I have a vertex array and another array containing the triangle indices:

#define X .525731112119133606
#define Z .850650808352039932
static GLfloat vdata[12][3] =
{-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z},
{0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
{Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}

static GLuint tindices[20][3] =
{1, 4, 0}, {4, 9, 0}, {4, 5, 9}, {8, 5, 4}, {1, 8, 4},
{1, 10, 8}, {10, 3, 8}, {8, 3, 5}, {3, 2, 5}, {3, 7, 2},
{3, 10, 7}, {10, 6, 7}, {6, 11, 7}, {6, 0, 11}, {6, 1, 0},
{10, 1, 6}, {11, 0, 9}, {2, 11, 9}, {5, 2, 9}, {11, 2, 7}

Of course these vertices lie on a spherical surface --but let’s suppose they are not.

Now how do you calculate the average of the normals?

UC San Diego

i just took the code out of my program, and of course without the context it is difficult to understand.
I just saw that the example code of you is from the RED BOOK. So i suppose that you have it. On page 667 you will find the idea of my solution.
The only question that might exist after reading this 2 pages (on page 665 you will find the perfect solution, maybe you are majoring in physics or mathematics )
how to ensure that for every arbitrary surface that consists of triangles your code will work.
Since you know all the vertices and the number of triangles you could paint the whole surface just by painting every sole triangle (slow of course).
Why i mention this ? Because you dont know how many triangles a particular vertex is component of (excuse my english -> not my mother-tongue). Let`s say that vertex B is component of 13 triangles, that means that you have to add 13 normals normalize the result and this will be the normal for vertex B. Now if you would have a code that renders all the triangles, you can be sure that vertex B will occure 13 times (exactly ). Now all the 13 times you know which particular triangle is rendered, as you know all the triangle-normals you know now also this particular normal.

Maybe you have now some clue what my code does -> this is one possible solution.
In my code i am using structures for the vertices, nx,ny,nz are just components of a vertex structure that hold the normal compon. while adding them.
The normal_arr just holds the previously calculated normals of the triangles not the averaged ones.
This way i connect the normal and the vertex compon. tightly, but i think you can`t use vertex arrays etc. anymore -> that is the disadvantage.

If you are going to average surface normals to get vertex normals, you might as well take the small extra step of considering smoothing groups. Or if this type of smoothing just isn’t good enough, you may consider using subdivision surfaces in addition to smoothing groups.

[This message has been edited by DFrey (edited 08-12-2002).]

Smoothing groups…what do you mean with that ?
Subdivision is good…unless you try to animate it…

Smoothing groups are a collection of polygons that have averaged normals at the vertices. This leads to a smoother look to the rendered geometry.