3D object draw/hidden surfaces .....

Hello,
I have a 3D object.
I draw it by drawing all its surfaces.The camera location
can be choosen randomly.(And the light sourse is place in rthe camera place)
How do I draw the surfaces correctly ?
Is the order of surfaces drawing important?
need draw them back to from probably according to the camera position or it is not important…?

thanks

The order is really relevant if your object is very complex and you are using fragment shaders that require significant amount of GPU shading unit time. Considering HyperZ or similar technologies, rendering should be done front to back (the opposite way you should expect).

But in your case, I guess that rendering order is totally irrelevant. Just enable depth test and everything will work fine.

In the scene preparation function just add

glEnable(GL_DEPTH_TEST);

and at the beginning of the drawing function clear depth buffer (along with frame buffer) with

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

After that you can freely draw in the order you want. :wink:

P.S. Drawing may require polygon sorting if you want to implement some kind of transparency.

Thank you for the answer!
The problem is that dispite the “light is placed in the camera”
The object drown ,looks like lighted from the side…

The problem can be in light position, but also in normals calculation.
If you want light source to be at the camera position, just set light source position at coordinates (0,0,0) after switching to modelview matrix and before the viewing transformation (for example, before gluLookAt).

The problematic result,I get:

The light source is definitely not at the viewer position. Did you set light position at (0,0,0) in clip coordinates?

yes.
I`ll be very thenkful if you could look at the code:


//Projection
                        glMatrixMode(GL_PROJECTION);
			glLoadIdentity();
            

			GLdouble diam = m_allModels.getDiam();
			GLdouble left = m_allModels.getCenter()[0] - diam;
			GLdouble right = m_allModels.getCenter()[0] + diam;
			GLdouble bottom = m_allModels.getCenter()[1] - diam;
			GLdouble top = m_allModels.getCenter()[1] + diam;

            
			glFrustum(left,right,bottom,top,diam,diam*3.5);            
           
//Model
                         glMatrixMode(GL_MODELVIEW);
                         glLoadIdentity();
			 gluLookAt (0.0, 0.0,2*m_allModels.getDiam(),
			m_allModels.getCenter()[0],m_allModels.getCenter()[1],m_allModels.getCenter()[2],
			0.0, 1.0, 0.0);

//Lighting
			GLfloat light_position[] = {0.0, 0.0,0.0, 1.0 };
			GLfloat white_light[] = { 0.7, 0.3, 0.2, 1.0 };
			glEnable(GL_DEPTH_TEST);
			
			
			glEnable(GL_LIGHTING);
			glLightfv(GL_LIGHT1, GL_POSITION, light_position);
			glLightfv(GL_LIGHT1, GL_DIFFUSE, white_light);
			glEnable(GL_LIGHT1);
                        glShadeModel(GL_FLAT);
			
//Draw
			glEnable(GL_NORMALIZE);
                        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//render here
for(unsigned int modelIdx = 0;modelIdx < m_allModels.zise();++modelIdx)
			{
				model curModel = m_allModels.getModel(modelIdx);
				for(unsigned int modelSurfIdx = 0;modelSurfIdx <curModel.surfNum();
					++modelSurfIdx)
				{
					surface curSurf = curModel.getSurface(modelSurfIdx);
					glLineWidth(2);
					glBegin( GL_POLYGON );

					
					glNormal3f(curSurf.getN_x(),curSurf.getN_y(),curSurf.getN_z());
					for(unsigned int vertIdx = 0;vertIdx< curSurf.size();++vertIdx)
					{
						unsigned int curVertIdx = curSurf.getSurfVertices()[vertIdx];
						vertex curVert = curModel.getVertex(curVertIdx);
						glVertex3f((GLfloat)curVert.getX(),(GLfloat)curVert.getY(),(GLfloat)curVert.getZ());
					}	
					glEnd();

				}
			}
 

Than I don’t have any idea. Post a code fragment where you set the light position.

the code is added in the above post
thanks

You didn’t obey my advice!
The light is not at the viewer’s position.
Set light position to (0,0,0) before gluLookAt!

It didn`t help…

You didn’t get it again. :frowning:
Hm…
You should write something like this:


glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//---------------------------
GLfloat light_position[] = {0.0, 0.0,0.0, 1.0 };
GLfloat white_light[] = { 0.7, 0.3, 0.2, 1.0 };
glLightfv(GL_LIGHT1, GL_POSITION, light_position);
glLightfv(GL_LIGHT1, GL_DIFFUSE, white_light);
//---------------------------
gluLookAt (...);

You have probably changed the position of this statement

GLfloat white_light[] = { 0.7, 0.3, 0.2, 1.0 };

which changes nothing!
It is important where you put this statement

glLightfv(GL_LIGHT1, GL_POSITION, light_position);

And, please, remove glShadeModel(GL_FLAT); It makes lighting inadequate by disabling interpolation between vertices.

No I changed/re-arranged the code placing light_position
as you said.

Any case it doesn`t change the result…

It should change. The position is quite different.
Post “the rearranged” code, please.


glEnable(GL_DEPTH_TEST);

             //projection
                        glMatrixMode(GL_PROJECTION);
			glLoadIdentity();

			GLdouble diam = m_allModels.getDiam();
			GLdouble left = m_allModels.getCenter()[0] - diam*1.5;
			GLdouble right = m_allModels.getCenter()[0] + diam*1.5;
			GLdouble bottom = m_allModels.getCenter()[1] - diam*1.5;
			GLdouble top = m_allModels.getCenter()[1] + diam*1.5;

            
			glFrustum(left,right,bottom,top,0.9,2*diam + 2);           
           
			 //Lighting
			glMatrixMode(GL_MODELVIEW);
                        glLoadIdentity();
            

			GLfloat light_position[] = {0.0,0.0,0.0, 1.0 };
			GLfloat red_light[] = { 0.7, 0.3, 0.2, 1.0 };

			
			glLightfv(GL_LIGHT1, GL_POSITION, light_position);
			glLightfv(GL_LIGHT1, GL_DIFFUSE, red_light);
			glEnable(GL_LIGHTING);
			glEnable(GL_LIGHT1);
            

			//model
            
			gluLookAt (0.0,0.0,m_allModels.getCenter()[2]-diam - 1,
			m_allModels.getCenter()[0],m_allModels.getCenter()[1],m_allModels.getCenter()[2],
			0.0, 1.0, 0.0);

           
			
			//Draw
			glEnable(GL_NORMALIZE);
                        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 			//render here

OK! We have eliminated the problem with the light position. Now it is at the right position. But there is still the problem with the normals, perhaps.
Take a look at the model. Some faces oriented “up” as well as some faces oriented “down” are equally lighted. Check the functions that calculate normals.

I think the normals are computed correctly
(according to Hill`s book) the normal for the plane
(A,B,C)
A = sum((Y(i)-Y(i+1)*(Z(i)*Z(i+1))
etc…


//////////////////////////////////////////////////////////////////////////////
// Function name: setNormal                                                 //
// Input parametrs:                                                         //
//       - vertexVector[vector<vertex>&] :Vector of all vertices            //
// Output parameters:                                                       //
//       - none                                                             //
// Functionality:                                                           //
//        Set Normal for the surface based on its vertexes                  //
//////////////////////////////////////////////////////////////////////////////
void surface::setNormal(vector<vertex>& vertexVector)
{
	unsigned int curVertIdx,nextVertIdx; 
	bool curVertFlag = false;

	//Iterate all surface vertices
	for(vector<unsigned int>::iterator vertSurfIt= m_surfVertices.begin();
		vertSurfIt != m_surfVertices.end();++vertSurfIt)
	{
		//Set curVertIdx for the first vertex
		if(!curVertFlag)
		{
			curVertIdx = *vertSurfIt;
			curVertFlag = true;
		}
		//Set nextVertIdx for the not first vertex,update curVertIdx
		//update the normal vector for the surface
		else
		{
			nextVertIdx = *vertSurfIt;
			normalUpdate(vertexVector,curVertIdx,nextVertIdx);
            curVertIdx = nextVertIdx;
		}
	}
	normalUpdate(vertexVector,curVertIdx,0);
	
}
//////////////////////////////////////////////////////////////////////////////
// Function name: normalUpdate                                              //
// Input parametrs:                                                         //
//       - vertexVector[vector<vertex>&] :  Vector of all vertices          //
//       - curVertIdx[unsigned int] : Current vertex index                  //
//       - curVertIdx[unsigned int] : Next vertex index                     //
// Output parameters:                                                       //
//       - none                                                             //
// Functionality:                                                           //
//        Update the normal vector                                          //
//////////////////////////////////////////////////////////////////////////////
void surface::normalUpdate(vector<vertex>& vertexVector,unsigned int curVertIdx,
						   unsigned int nextVertIdx)
{
	//Normal x part
	n_x = n_x + 
		(vertexVector[curVertIdx].getY() - vertexVector[nextVertIdx].getY())*
		(vertexVector[curVertIdx].getZ() + vertexVector[nextVertIdx].getZ());
	//Normal y part
	n_y = n_y + 
		(vertexVector[curVertIdx].getZ() - vertexVector[nextVertIdx].getZ())*
		(vertexVector[curVertIdx].getX() + vertexVector[nextVertIdx].getX());
	//Normal z part
	n_z = n_z + 
		(vertexVector[curVertIdx].getX() - vertexVector[nextVertIdx].getX())*
		(vertexVector[curVertIdx].getY() + vertexVector[nextVertIdx].getY());
}



I’ve been fooling around with your code by drawing a teapot instead of your object. I got the same results you did when I tried moving the glLightfv(…, light_position) command around. It didn’t fix the lighting problem. What works for me is to put the light at the same location as the camera (first 3 values of LookAt). This only requires one line of code -

light_position[2] = m_allModels.getCenter()[2]-diam - 1;

Do this somewhere before the call to glLightfv(., light_position)

I am afraid that may be the problem is in the
incorrect hidden surfaces removal and I have to use stencil test /or dot product of the vector from camera with the normal of surface plane /or the way I try to examine the depth is incorrect and I have to add some additional code…(whatever :confused:)

Any case,thank you very much for the answer,I`ll try as you said!!!

I have found the reason for the error in the rendering image-the normals!!!
The way I was calculating them is by Martin Newell method.
But the problem is in the directions.So I tried to define correct directions by finding center of mass of the 3D object and the center of mass of each surface and findig the dot product between vector leading from center of mass of the surface with the normal to the surface.If it is negative the normal direction is corret else it has to be negated.
But this way is not optimal…Doesnt work good for not convex objects... Will be very thankfull for some advices (I don want to use cross product …)