Jump to content
  • Advertisement
Sign in to follow this  
Dragon_Strike

OpenGL calculating the vertex normal and tangent of model * solved

This topic is 4150 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

im trying to get model loading working in my program... ive found the following code for this... however.. im unsure how i would go about to calculate the vertex normals and tangents since im only able to get the verties of one triangle.. and not the vertices of neighboring triangles to be able to perform these calcultions.. how would i go about gettin the vertices required? its a 3ds model im trying to load
					case CHUNK_TRIOBJ:
						{
							ucpTmp += 6;
							uiMeshBytesRead += 6;
							break;
						}
						//its a list of vertices!
					case CHUNK_VERTLIST:
						{
							//skip the header
							unsigned char * ucpTmp2 = ucpTmp;
							ucpTmp2 += 6;
							unsigned short usNumVerts = *(unsigned short *)ucpTmp2;
							ucpTmp2 += 2;
						//	//Read vertices 1 by 1
							for(int x = 0; x < usNumVerts; x++)
							{
								//Read the vertices, changing them to openGl's coordinate system
								m_vMeshes[iCurMesh]->m_vVertices.push_back(new S3dsVertex);
								m_vMeshes[iCurMesh]->m_vVertices[x]->m_fVert[0] = *(float *)&ucpTmp2[0];
								m_vMeshes[iCurMesh]->m_vVertices[x]->m_fVert[1] = *(float *)&ucpTmp2[4];
								m_vMeshes[iCurMesh]->m_vVertices[x]->m_fVert[2] = *(float *)&ucpTmp2[8];
								ucpTmp2 += 12;
//								Log.Write(COLOR_YELLOW, "%f %f %f", m_vMeshes[iCurMesh]->m_vVertices[x].fVert[0],m_vMeshes[iCurMesh]->m_vVertices[x].fVert[1],m_vMeshes[iCurMesh]->m_vVertices[x].fVert[2]);
							}
							ucpTmp += subChunk->m_uiLength;
							uiMeshBytesRead += subChunk->m_uiLength;
							break;
						}
						//Face information
					case CHUNK_TRILIST:
						{
							unsigned int uiTriBytesRead = 8;
							//skip the header
							ucpTmp += 6;
							//Get the number of triangles
							unsigned short usNumPolys = *(unsigned short *)ucpTmp;
							m_vMeshes[iCurMesh]->m_usNumFaces = usNumPolys;
							ucpTmp += 2;

							S3dsVertex ** pVert = &m_vMeshes[iCurMesh]->m_vVertices[0];					
							//Read the triangles
							for(int x = 0; x < usNumPolys; x++)
							{
								m_vMeshes[iCurMesh]->m_vFaces.push_back(new S3dsFace);
								S3dsFace * pFace = m_vMeshes[iCurMesh]->m_vFaces[x];
								pFace->m_usIndices[0] = *(unsigned short *)&ucpTmp[0];
								pFace->m_usIndices[1] = *(unsigned short *)&ucpTmp[2];
								pFace->m_usIndices[2] = *(unsigned short *)&ucpTmp[4];
								//Calculate Face Normal
								pFace->m_vecNormal = CalcFaceNormal(CVector3(pVert[pFace->m_usIndices[0]]->m_fVert), 
									                                CVector3(pVert[pFace->m_usIndices[1]]->m_fVert), 
																	CVector3(pVert[pFace->m_usIndices[2]]->m_fVert));
								ucpTmp += 8;
								uiTriBytesRead += 8;
							}
							int iCurObjMat = 0;
							while(uiTriBytesRead < subChunk->m_uiLength)
							{
								S3dsChunkHeader * sub2Chunk = (S3dsChunkHeader *)ucpTmp;
								//Material properties
								if(sub2Chunk->m_usID == CHUNK_OBJMAT)
								{
									
									ucpTmp += 6;
									char cMatName[64];
									//Get material name
									strcpy(cMatName, (char *)ucpTmp);
									//Find the index
									m_vMeshes[iCurMesh]->m_vMaterials.push_back(new S3dsObjMat);
									m_vMeshes[iCurMesh]->m_vMaterials[iCurObjMat]->m_usMatIdx = 0;
									for(int x = 0; x < m_vMaterials.size(); x++)
									{
										if(strcmp(cMatName, m_vMaterials[x]->m_cName) == 0)
											m_vMeshes[iCurMesh]->m_vMaterials[iCurObjMat]->m_usMatIdx = x;
									}
									//Read face indices
									unsigned int uiObjMatBytesRead = 9 + strlen(cMatName);
									ucpTmp += strlen(cMatName) + 3;

									while(uiObjMatBytesRead < sub2Chunk->m_uiLength)
									{
										unsigned short usFace =  *(unsigned short *)ucpTmp;
										m_vMeshes[iCurMesh]->m_vMaterials[iCurObjMat]->m_vFaceIndices.push_back(usFace);
										ucpTmp += 2;
										uiObjMatBytesRead += 2;
									}

									iCurObjMat++;
									uiTriBytesRead += sub2Chunk->m_uiLength;
								}
								else
								{
									ucpTmp += sub2Chunk->m_uiLength;
									uiTriBytesRead += sub2Chunk->m_uiLength;
								}
							}
							uiMeshBytesRead += subChunk->m_uiLength;
							break;
						}



[Edited by - Dragon_Strike on May 13, 2007 5:45:10 AM]

Share this post


Link to post
Share on other sites
Advertisement
I don't know the official way to do something like this, but I would first construct a list of every vertex in all the triangles, and remove all the duplicates. From this, construct 2 identically sized lists that contain normal data and a count of how many triangles a vertex belongs to.

Then, I would iterate over each triangle, finding its verticies in the list and adding its normal to the normal list and incrementing the count in the count list.

Then, iterate over all the verticies and divide the normal data by the count for each vertex and normalize the result. This is the normal for that vertex.

Share this post


Link to post
Share on other sites
IIRC, this is the way I did it:
-I computed the normal of every vertex relative of their own triangle. Don't worry in this step if there are duplicates, treat them just as they were different vertices.
-Iterate over the list of triangles and take the average of the duplicates, building a new list of normals:

ie:
for(int i = 0; i < trilist.Count(); ++i)
{
trilist.ComputeNormal();
}

trianglelist newtrilist = new trianglelist;
for(int i = 0; i < trilist.Count(); ++i)
{
int c = 0;
for(int j = 0; j = i+1; ++j)
{
if(trilist[j] == trilist)
{
trilist.Normal += trilist[j].Normal
delete trilist[j];
++c
}
trilist.Normal /= c;
}
newtrilist.Add(trilist);
}

And of course, sorry for the code (that reminds me I should refresh my c++ skills)
Hope this helps!

Share this post


Link to post
Share on other sites
im not quite with ya...

im alrdy calculating the face normals... and to get the vertex normal i take the avarge of all the facenormals that the vertex is connected to.. however my problem is that i dont know how to determine which faces the vertex connects to..


EDIT:: I think i undestadn waht you mean now.. ill try it..

[Edited by - Dragon_Strike on May 13, 2007 4:04:20 AM]

Share this post


Link to post
Share on other sites
would it be correct if u just simply added all the facenormals the vertex is connected to.. without averaging.. but instead normalizing in the vertex shader?

EDIT::

another solution i guess...



case CHUNK_TRILIST:
{
unsigned int uiTriBytesRead = 8;
//skip the header
ucpTmp += 6;
//Get the number of triangles
unsigned short usNumPolys = *(unsigned short *)ucpTmp;
m_vMeshes[iCurMesh]->m_usNumFaces = usNumPolys;
ucpTmp += 2;

S3dsVertex ** pVert = &m_vMeshes[iCurMesh]->m_vVertices[0];
//Read the triangles
for(int x = 0; x < usNumPolys; x++)
{
m_vMeshes[iCurMesh]->m_vFaces.push_back(new S3dsFace);
S3dsFace * pFace = m_vMeshes[iCurMesh]->m_vFaces[x];
pFace->m_usIndices[0] = *(unsigned short *)&ucpTmp[0];
pFace->m_usIndices[1] = *(unsigned short *)&ucpTmp[2];
pFace->m_usIndices[2] = *(unsigned short *)&ucpTmp[4];
//Calculate Face Normal
pFace->m_vecNormal = CalcFaceNormal(CVector3(pVert[pFace->m_usIndices[0]]->m_fVert),
CVector3(pVert[pFace->m_usIndices[1]]->m_fVert),
CVector3(pVert[pFace->m_usIndices[2]]->m_fVert));




int curindex;

curindex = pVert[pFace->m_usIndices[0]]->index;
pVert[pFace->m_usIndices[0]]->m_fNormal = pVert[pFace->m_usIndices[0]]->m_fNormal * (1.0f-1.0f/(float)curindex) + pFace->m_vecNormal*(1.0f/(float)curindex);
pVert[pFace->m_usIndices[0]]->index++;


curindex = pVert[pFace->m_usIndices[1]]->index;
pVert[pFace->m_usIndices[1]]->m_fNormal = pVert[pFace->m_usIndices[1]]->m_fNormal * (1.0f-1.0f/(float)curindex) + pFace->m_vecNormal*(1.0f/(float)curindex);
pVert[pFace->m_usIndices[1]]->index++;


curindex = pVert[pFace->m_usIndices[2]]->index;
pVert[pFace->m_usIndices[2]]->m_fNormal = pVert[pFace->m_usIndices[2]]->m_fNormal * (1.0f-1.0f/(float)curindex) + pFace->m_vecNormal*(1.0f/(float)curindex);
pVert[pFace->m_usIndices[2]]->index++;





EDIT2;;

however i still have problems at edge areas and other...

Free Image Hosting at www.ImageShack.us

[Edited by - Dragon_Strike on May 13, 2007 5:52:22 AM]

Share this post


Link to post
Share on other sites
hm... i think ive got some idea whats causing the problm...

when i load the model in 3d max.. i get several normals for on vertex (there are several vertices at the same place)... when i weld these togheter and then export the file as 3ds... then open it again.. the vertices are seperated.. wahts causing this? is it something to do with the 3ds format?

EDIT:: it was the models fault.. solved

[Edited by - Dragon_Strike on May 13, 2007 5:28:35 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!