calculating the vertex normal and tangent of model * solved

Started by
4 comments, last by Dragon_Strike 16 years, 11 months ago
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]
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.
[size=2]Darwinbots - [size=2]Artificial life simulation
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!
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]
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]
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]

This topic is closed to new replies.

Advertisement