# 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.

## 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;
break;
}
//its a list of vertices!
case CHUNK_VERTLIST:
{
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;
break;
}
//Face information
case CHUNK_TRILIST:
{
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];
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;
}
int iCurObjMat = 0;
{
//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;
}
unsigned int uiObjMatBytesRead = 9 + strlen(cMatName);
ucpTmp += strlen(cMatName) + 3;

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

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


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

##### Share on other sites
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 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;
}
}

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

##### 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 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...

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

##### 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]

1. 1
2. 2
Rutin
18
3. 3
4. 4
5. 5
frob
12

• 9
• 21
• 11
• 9
• 17
• ### Forum Statistics

• Total Topics
632606
• Total Posts
3007381

×