void CLoadASE::ComputeNormals(t3DModel *pModel) { CVector3 vVector1, vVector2, vNormal, vPoly[3]; if(pModel->numOfObjects <= 0) return; for(int index = 0; index < pModel->numOfObjects; index++) { t3DObject *pObject = &(pModel->pObject[index]); CVector3 *pNormals = new CVector3 [pObject->numOfFaces]; CVector3 *pTempNormals = new CVector3 [pObject->numOfFaces]; pObject->pNormals = new CVector3 [pObject->numOfVerts]; for(int i=0; i < pObject->numOfFaces; i++) { vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]]; vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]]; vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]]; vVector1 = Vector(vPoly[0], vPoly[2]); vVector2 = Vector(vPoly[2], vPoly[1]); vNormal = Cross(vVector1, vVector2); pTempNormals[i] = vNormal; vNormal = Normalize(vNormal); pObject->pFaces[i].Normal=MultiplieVectorByScaler(vNormal,-1.0f); pNormals[i] = vNormal; } CVector3 vSum = {0.0, 0.0, 0.0}; CVector3 vZero = vSum; int shared=0; for(int i = 0; i < pObject->numOfVerts; i++) { for (int j = 0; j < pObject->numOfFaces; j++) { if (pObject->pFaces[j].vertIndex[0] == i || pObject->pFaces[j].vertIndex[1] == i || pObject->pFaces[j].vertIndex[2] == i) { vSum = AddVector(vSum, pTempNormals[j]); shared++; } } pObject->pNormals[i] = DivideVectorByScaler(vSum, float(-shared)); pObject->pNormals[i] = Normalize(pObject->pNormals[i]); vSum = vZero; shared = 0; } delete [] pTempNormals; delete [] pNormals; } }
// 下面的函数用于计算对象的法向量 void CLoad3DS::ComputeNormals(t3DModel *pModel) { CVector3 vVector1, vVector2, vNormal, vPoly[3]; // 如果模型中没有对象,则返回 if(pModel->numOfObjects <= 0) return; // 遍历模型中所有的对象 for(int index = 0; index < pModel->numOfObjects; index++) { // 获得当前的对象 t3DObject *pObject = &(pModel->pObject[index]); // 分配需要的存储空间 CVector3 *pNormals = new CVector3 [pObject->numOfFaces]; CVector3 *pTempNormals = new CVector3 [pObject->numOfFaces]; pObject->pNormals = new CVector3 [pObject->numOfVerts]; // 遍历对象的所有面 for(int i=0; i < pObject->numOfFaces; i++) { vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]]; vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]]; vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]]; // 计算面的法向量 vVector1 = Vector(vPoly[0], vPoly[2]); // 获得多边形的矢量 vVector2 = Vector(vPoly[2], vPoly[1]); // 获得多边形的第二个矢量 vNormal = Cross(vVector1, vVector2); // 获得两个矢量的叉积 pTempNormals[i] = vNormal; // 保存非规范化法向量 vNormal = Normalize(vNormal); // 规范化获得的叉积 pNormals[i] = vNormal; // 将法向量添加到法向量列表中 } // 下面求顶点法向量 CVector3 vSum = {0.0, 0.0, 0.0}; CVector3 vZero = vSum; int shared=0; // 遍历所有的顶点 for (int i = 0; i < pObject->numOfVerts; i++) { for (int j = 0; j < pObject->numOfFaces; j++) // 遍历所有的三角形面 { // 判断该点是否与其它的面共享 if (pObject->pFaces[j].vertIndex[0] == i || pObject->pFaces[j].vertIndex[1] == i || pObject->pFaces[j].vertIndex[2] == i) { vSum = AddVector(vSum, pTempNormals[j]); shared++; } } pObject->pNormals[i] = DivideVectorByScaler(vSum, float(-shared)); // 规范化最后的顶点法向 pObject->pNormals[i] = Normalize(pObject->pNormals[i]); vSum = vZero; shared = 0; } // 释放存储空间,开始下一个对象 delete [] pTempNormals; delete [] pNormals; } }
void CLoad3DS::ComputeNormals(t3DModel *pModel) { CVector3 vVector1, vVector2, vNormal, vPoly[3]; // If there are no objects, we can skip this part if(pModel->numOfObjects <= 0) return; // What are vertex normals? And how are they different from other normals? // Well, if you find the normal to a triangle, you are finding a "Face Normal". // If you give OpenGL a face normal for lighting, it will make your object look // really flat and not very round. If we find the normal for each vertex, it makes // the smooth lighting look. This also covers up blocky looking objects and they appear // to have more polygons than they do. Basically, what you do is first // calculate the face normals, then you take the average of all the normals around each // vertex. It's just averaging. That way you get a better approximation for that vertex. // Go through each of the objects to calculate their normals for(int index = 0; index < pModel->numOfObjects; index++) { // Get the current object t3DObject *pObject = &(pModel->pObject[index]); // Here we allocate all the memory we need to calculate the normals CVector3 *pNormals = new CVector3 [pObject->numOfFaces]; CVector3 *pTempNormals = new CVector3 [pObject->numOfFaces]; pObject->pNormals = new CVector3 [pObject->numOfVerts]; // Go though all of the faces of this object for(int i=0; i < pObject->numOfFaces; i++) { // To cut down LARGE code, we extract the 3 points of this face vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]]; vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]]; vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]]; // Now let's calculate the face normals (Get 2 vectors and find the cross product of those 2) vVector1 = Vector(vPoly[0], vPoly[2]); // Get the vector of the polygon (we just need 2 sides for the normal) vVector2 = Vector(vPoly[2], vPoly[1]); // Get a second vector of the polygon vNormal = Cross(vVector1, vVector2); // Return the cross product of the 2 vectors (normalize vector, but not a unit vector) pTempNormals[i] = vNormal; // Save the un-normalized normal for the vertex normals vNormal = Normalize(vNormal); // Normalize the cross product to give us the polygons normal pNormals[i] = vNormal; // Assign the normal to the list of normals } //////////////// Now Get The Vertex Normals ///////////////// CVector3 vSum = {0.0, 0.0, 0.0}; CVector3 vZero = vSum; int shared=0; for (int i = 0; i < pObject->numOfVerts; i++) // Go through all of the vertices { for (int j = 0; j < pObject->numOfFaces; j++) // Go through all of the triangles { // Check if the vertex is shared by another face if (pObject->pFaces[j].vertIndex[0] == i || pObject->pFaces[j].vertIndex[1] == i || pObject->pFaces[j].vertIndex[2] == i) { vSum = AddVector(vSum, pTempNormals[j]);// Add the un-normalized normal of the shared face shared++; // Increase the number of shared triangles } } // Get the normal by dividing the sum by the shared. We negate the shared so it has the normals pointing out. pObject->pNormals[i] = DivideVectorByScaler(vSum, float(-shared)); // Normalize the normal for the final vertex normal pObject->pNormals[i] = Normalize(pObject->pNormals[i]); vSum = vZero; // Reset the sum shared = 0; // Reset the shared } // Free our memory and start over on the next object delete [] pTempNormals; delete [] pNormals; } }
/** computes the normals and vertex normals of the objects */ void Obj::computeNormals(tOBJModel *pmodel) { Vec3 vVector1, vVector2, vNormal, vPoly[3]; if (pmodel->numOfObjects <= 0) return; // if there are no objects, we can skip for (int index = 0; index < pmodel->numOfObjects; index++) { // for each of the objects tOBJObject *pobject = &(pmodel->pObject[index]); // get the current object Vec3 *pNormals = new Vec3 [pobject->numOfFaces]; Vec3 *pTempNormals = new Vec3 [pobject->numOfFaces]; pobject->pNormals = new Vec3 [pobject->numOfVerts]; for (int i=0; i < pobject->numOfFaces; i++) { // go though all of the faces // we extract the 3 points of this face int vx = pobject->pFaces[i].vertIndex[0]; int vy = pobject->pFaces[i].vertIndex[1]; int vz = pobject->pFaces[i].vertIndex[2]; int vc = pobject->numOfVerts; if (vx > vc || vy > vc || vz > vc) { error("Obj: vx=%d vy=%d vz=%d vc=%d", vx, vy, vz, vc); continue; //dax BUG: segfault } vPoly[0] = pobject->pVerts[pobject->pFaces[i].vertIndex[0]]; vPoly[1] = pobject->pVerts[pobject->pFaces[i].vertIndex[1]]; vPoly[2] = pobject->pVerts[pobject->pFaces[i].vertIndex[2]]; // let's calculate the face normals (get 2 vectors and find the cross product of those 2) vVector1 = Vector(vPoly[0], vPoly[2]); // get the vector of the polygon (we just need 2 sides) vVector2 = Vector(vPoly[2], vPoly[1]); // get a second vector of the polygon vNormal = Cross(vVector1, vVector2); // return the cross product of the 2 vectors pTempNormals[i] = vNormal; // save the un-normalized normal for the vertex normals vNormal = Normalize(vNormal); // normalize the cross product to give us the polygons normal pNormals[i] = vNormal; // assign the normal to the list of normals } Vec3 vSum = {0.0, 0.0, 0.0}; Vec3 vZero = vSum; int shared=0; // get the vertex normals for (int i=0; i < pobject->numOfVerts; i++) { // go through all of the vertices for (int j=0; j < pobject->numOfFaces; j++) {// go through all of the triangles // check if the vertex is shared by another face if (pobject->pFaces[j].vertIndex[0] == i || pobject->pFaces[j].vertIndex[1] == i || pobject->pFaces[j].vertIndex[2] == i) { vSum = AddVector(vSum, pTempNormals[j]); // add the unnormalized normal of the shared face shared++; // increase the number of shared triangles } } // get the normal by dividing the sum by the shared. we negate so normals pointing out. pobject->pNormals[i] = DivideVectorByScaler(vSum, float(-shared)); // normalize the normal for the final vertex normal pobject->pNormals[i] = Normalize(pobject->pNormals[i]); vSum = vZero; // reset the sum shared = 0; // reset the shared } if (pTempNormals) delete[] pTempNormals; if (pNormals) delete[] pNormals; } }
void CLoadASE::ComputeTangents(t3DModel *pModel) { CVector3 vVector1, vVector2, vTangent, vBinormal, vPoly[3]; float vVector1s, vVector1t, vVector2s, vVector2t; float v1s, v1t, v2s, v2t, v3s, v3t; CVector3 vSum = {0.0, 0.0, 0.0}; CVector3 vZero = vSum; int shared=0; if(pModel->numOfObjects <= 0) return; for(int index = 0; index < pModel->numOfObjects; index++) { t3DObject *pObject = &(pModel->pObject[index]); CVector3 *pTangents = new CVector3 [pObject->numOfFaces]; CVector3 *pTempTangents = new CVector3 [pObject->numOfFaces]; pObject->pTangents = new CVector3 [pObject->numOfVerts]; CVector3 *pBinormals = new CVector3 [pObject->numOfFaces]; CVector3 *pTempBinormals = new CVector3 [pObject->numOfFaces]; pObject->pBinormals = new CVector3 [pObject->numOfVerts]; for(int i=0; i < pObject->numOfFaces; i++) { vPoly[0] = pObject->pVerts[pObject->pFaces[i].vertIndex[0]]; vPoly[1] = pObject->pVerts[pObject->pFaces[i].vertIndex[1]]; vPoly[2] = pObject->pVerts[pObject->pFaces[i].vertIndex[2]]; v1s = pObject->pTexVerts[pObject->pFaces[i].coordIndex[0]].x; v1t = pObject->pTexVerts[pObject->pFaces[i].coordIndex[0]].y; v2s = pObject->pTexVerts[pObject->pFaces[i].coordIndex[1]].x; v2t = pObject->pTexVerts[pObject->pFaces[i].coordIndex[1]].y; v3s = pObject->pTexVerts[pObject->pFaces[i].coordIndex[2]].x; v3t = pObject->pTexVerts[pObject->pFaces[i].coordIndex[2]].y; vVector1 = Vector(vPoly[1], vPoly[0]); vVector2 = Vector(vPoly[2], vPoly[0]); vVector1s = v2s-v1s; vVector1t = v2t-v1t; vVector2s = v3s-v1s; vVector2t = v3t-v1t; float denominator = vVector1s * vVector2t - vVector2s * vVector1t; if(denominator < 0.0001f && denominator > -0.0001f) { vTangent.x = 1.0f; vTangent.y = 0.0f; vTangent.z = 0.0f; vBinormal.x = 0.0f; vBinormal.y = 1.0f; vBinormal.z = 0.0f; pTempTangents[i] = vTangent; pTempBinormals[i] = vBinormal; } else { float scale = 1.0f / denominator; CVector3 T, B, N; T.x = (vVector2t * vVector1.x - vVector1t * vVector2.x) * scale; T.y = (vVector2t * vVector1.y - vVector1t * vVector2.y) * scale; T.z = (vVector2t * vVector1.z - vVector1t * vVector2.z) * scale; B.x = (-vVector2s * vVector1.x + vVector1s * vVector2.x) * scale; B.y = (-vVector2s * vVector1.y + vVector1s * vVector2.y) * scale; B.z = (-vVector2s * vVector1.z + vVector1s * vVector2.z) * scale; N = pObject->pFaces[i].Normal; float scale2 = 1.0f / ((T.x * B.y * N.z - T.z * B.y * N.x) + (B.x * N.y * T.z - B.z * N.y * T.x) + (N.x * T.y * B.z - N.z * T.y * B.x)); vTangent.x = Cross(B, N).x * scale2; vTangent.y = -Cross(N, T).x * scale2; vTangent.z = Cross(T, B).x * scale2; pTempTangents[i] = vTangent; vTangent=Normalize(vTangent); vBinormal.x = -Cross(B, N).y * scale2; vBinormal.y = Cross(N, T).y * scale2; vBinormal.z = -Cross(T, B).y * scale2; pTempBinormals[i] = vBinormal; vBinormal=Normalize(vBinormal); } } vZero = vSum; shared=0; for(int i = 0; i < pObject->numOfVerts; i++) { for (int j = 0; j < pObject->numOfFaces; j++) { if (pObject->pFaces[j].vertIndex[0] == i || pObject->pFaces[j].vertIndex[1] == i || pObject->pFaces[j].vertIndex[2] == i) { vSum = AddVector(vSum, pTempTangents[j]); shared++; } } pObject->pTangents[i] = DivideVectorByScaler(vSum, float(shared)); pObject->pTangents[i] = Normalize(pObject->pTangents[i]); vSum = vZero; shared = 0; } delete [] pTempTangents; delete [] pTangents; vZero = vSum; shared=0; for(int i = 0; i < pObject->numOfVerts; i++) { for (int j = 0; j < pObject->numOfFaces; j++) { if (pObject->pFaces[j].vertIndex[0] == i || pObject->pFaces[j].vertIndex[1] == i || pObject->pFaces[j].vertIndex[2] == i) { vSum = AddVector(vSum, pTempBinormals[j]); shared++; } } pObject->pBinormals[i] = DivideVectorByScaler(vSum, float(-shared)); pObject->pBinormals[i] = Normalize(pObject->pBinormals[i]); vSum = vZero; shared = 0; } delete [] pTempBinormals; delete [] pBinormals; } }
void ComputeNormals(Loader3ds *pt3ds) { int i,j,index; int shared=0; float v1x=0.0,v1y=0.0,v1z=0.0, v2x=0.0,v2y=0.0,v2z=0.0, vnx=0.0,vny=0.0,vnz=0.0, vp0x=0.0,vp0y=0.0,vp0z=0.0, vp1x=0.0,vp1y=0.0,vp1z=0.0, vp2x=0.0,vp2y=0.0,vp2z=0.0, *pNormals=NULL, *pTempNormals=NULL, vSumx = 0.0,vSumy = 0.0,vSumz = 0.0; Objects *cur_obj; // If there are no objects, we can skip this part if(pt3ds->NBobjects <= 0) return; // Go through each of the objects to calculate their normals cur_obj = pt3ds->objects; for(index = 0; index < pt3ds->NBobjects; index++) { pNormals = (float*)malloc(sizeof(float) *(3*cur_obj->NBFaces)); pTempNormals = (float*)malloc(sizeof(float) * (3*cur_obj->NBFaces)); cur_obj->Normal = (float*)malloc(sizeof(float) * (3*cur_obj->NBvert)); // Go though all of the faces of this object for(i=0; i < cur_obj->NBFaces; i++) { vp0x=cur_obj->vert[0+3*cur_obj->Faces[i*3]]; vp0y=cur_obj->vert[1+3*cur_obj->Faces[i*3]]; vp0z=cur_obj->vert[2+3*cur_obj->Faces[i*3]]; vp1x=cur_obj->vert[0+3*cur_obj->Faces[i*3+1]]; vp1y=cur_obj->vert[1+3*cur_obj->Faces[i*3+1]]; vp1z=cur_obj->vert[2+3*cur_obj->Faces[i*3+1]]; vp2x=cur_obj->vert[0+3*cur_obj->Faces[i*3+2]]; vp2y=cur_obj->vert[1+3*cur_obj->Faces[i*3+2]]; vp2z=cur_obj->vert[2+3*cur_obj->Faces[i*3+2]]; Vector( vp0x,vp0y,vp0z, vp2x,vp2y,vp2z, &v1x,&v1y,&v1z); // Get the vector of the polygon (we just need 2 sides for the normal) Vector( vp2x,vp2y,vp2z, vp1x,vp1y,vp1z, &v2x,&v2y,&v2z); // Get a second vector of the polygon Cross( v1x,v1y,v1z, v2x,v2y,v2z, &vnx,&vny,&vnz); // Return the cross product of the 2 vectors (normalize vector, but not a unit vector) pTempNormals[3*i] = vnx; // Save the un-normalized normal for the vertex normals pTempNormals[3*i+1] = vny; // Save the un-normalized normal for the vertex normals pTempNormals[3*i+2] = vnz; // Save the un-normalized normal for the vertex normals Normalize(&vnx,&vny,&vnz); // Normalize the cross product to give us the polygons normal pNormals[3*i] = vnx; // Assign the normal to the list of normals pNormals[3*i+1] = vny; // Assign the normal to the list of normals pNormals[3*i+2] = vnz; // Assign the normal to the list of normals } //////////////// Now Get The Vertex Normals ///////////////// vSumx = 0.0;vSumy = 0.0;vSumz = 0.0; shared=0; for (i = 0; i < cur_obj->NBvert; i++) // Go through all of the vertices { for (j = 0; j < cur_obj->NBFaces; j++) // Go through all of the triangles { // Check if the vertex is shared by another face if (cur_obj->Faces[j*3] == i || cur_obj->Faces[j*3+1] == i || cur_obj->Faces[j*3+2] == i) { AddVector( vSumx,vSumy,vSumz, pTempNormals[j*3],pTempNormals[j*3+1],pTempNormals[j*3+2], &vSumx,&vSumy,&vSumz);// Add the un-normalized normal of the shared face shared++; // Increase the number of shared triangles } } // Get the normal by dividing the sum by the shared. We negate the shared so it has the normals pointing out. DivideVectorByScaler( vSumx,vSumy,vSumz, &(cur_obj->Normal[i*3]), &(cur_obj->Normal[i*3+1]), &(cur_obj->Normal[i*3+2]), -(float)shared); // Normalize the normal for the final vertex normal Normalize( &(cur_obj->Normal[i*3]), &(cur_obj->Normal[i*3+1]), &(cur_obj->Normal[i*3+2])); vSumx = 0.0;vSumy = 0.0;vSumz = 0.0; // Reset the sum shared = 0; // Reset the shared } if (pNormals) free(pNormals); if (pTempNormals) free(pTempNormals); cur_obj=cur_obj->next; }//end for index }