static bool MakeNormalMesh(plMaxNode *node, plMaxMeshExtractor::NeutralMesh& mesh, Matrix3* w2l) { TriObject *pDeleteMe = nil; Mesh *pMesh = ExtractMesh(node, &pDeleteMe); // allocates *sometimes*; check pDeleteMe if (!pMesh) return false; Matrix3 fullTM = node->GetObjectTM(0); int parity = fullTM.Parity(); mesh.fNumVerts = pMesh->numVerts; mesh.fVerts = new hsPoint3[mesh.fNumVerts]; for (int i = 0; i < mesh.fNumVerts; i++) { // convert the vertex to global coordinates Point3 newVert = fullTM * pMesh->verts[i]; // convert the vertex to the new (requested) coordinate system if (w2l) newVert = (*w2l) * newVert; mesh.fVerts[i].Set(newVert.x, newVert.y, newVert.z); } mesh.fNumFaces = pMesh->numFaces; mesh.fFaces = new uint16_t[mesh.fNumFaces*3]; for (int i = 0; i < mesh.fNumFaces; i++) { Face* pFace = &pMesh->faces[i]; uint16_t* pNFace = &mesh.fFaces[i * 3]; pNFace[0] = pFace->v[ parity ? 2 : 0 ]; // reverse winding if parity backwards pNFace[1] = pFace->v[1]; pNFace[2] = pFace->v[ parity ? 0 : 2 ]; // '' } if (pDeleteMe) delete pDeleteMe; return true; }
void LightMesh::AddMesh(Mesh *m, Matrix3 basetm, ViewExp *vpt, BOOL buildVNorms) { //copy over the vert and face data vertsViewSpace.SetCount(m->numVerts); for (int i =0; i < m->numVerts; i++) vertsViewSpace[i] = m->verts[i]; vertsWorldSpace = vertsViewSpace; BOOL flip = basetm.Parity();//check to see if the mesh has been mirrored if so flip stuff; faces.SetCount(m->numFaces); for (i =0; i < m->numFaces; i++) { faces[i] = m->faces[i]; if (flip) { int a = faces[i].v[0]; int b = faces[i].v[1]; int c = faces[i].v[2]; faces[i].v[0] = c; faces[i].v[1] = b; faces[i].v[2] = a; } } toWorldSpace = basetm; toLocalSpace = Inverse(basetm); for (i =0; i < m->numVerts; i++) vertsWorldSpace[i] = vertsWorldSpace[i]*basetm; bb.Init(); //build vnorms and fnorms Mesh *mesh; mesh = m; Face *face; Point3 v0, v1, v2; // face = m->faces; face = faces.Addr(0); // fnorms.SetCount(m->getNumFaces()); GraphicsWindow *gw = vpt->getGW(); Matrix3 tm; vpt->GetAffineTM(tm); gw->setTransform(Matrix3(1)); Point3 *verts = vertsViewSpace.Addr(0); int vertCount = vertsViewSpace.Count(); for (i =0; i < vertCount; i++) { Point3 inPoint,outPoint; inPoint = *verts * basetm; DWORD flag = gw->transPoint(&inPoint, &outPoint); inPoint = inPoint * tm; *verts = outPoint ; (*verts).z = inPoint.z; bb += *verts; verts++; } // Compute face and vertex surface normals faceVisible.SetSize(m->getNumFaces()); faceVisible.ClearAll(); for (i = 0; i < m->getNumFaces(); i++, face++) { // Calculate the surface normal Point3 norm; v0 = vertsViewSpace[face->v[0]]; v1 = vertsViewSpace[face->v[1]]; v2 = vertsViewSpace[face->v[2]]; norm = (v1-v0)^(v2-v1); if (norm.z < 0.0f) { if (face->Hidden()) faceVisible.Set(i,FALSE); else faceVisible.Set(i,TRUE); } else faceVisible.Set(i,FALSE); } if (buildVNorms) { face = faces.Addr(0); Tab<int> normCount; normCount.SetCount(m->numVerts); vnorms.SetCount(m->numVerts); for (i = 0; i < m->numVerts; i++) { vnorms[i] = Point3(0.0f,0.0f,0.0f); normCount[i] = 0; } for (i = 0; i < mesh->getNumFaces(); i++, face++) { // Calculate the surface normal v0 = vertsWorldSpace[face->v[0]]; v1 = vertsWorldSpace[face->v[1]]; v2 = vertsWorldSpace[face->v[2]]; for (int j=0; j<3; j++) { vnorms[face->v[j]]+=Normalize((v1-v0)^(v2-v1)); normCount[face->v[j]]++; } } for (i = 0; i < m->numVerts; i++) { if (normCount[i]!=0) vnorms[i] = Normalize(vnorms[i]/(float)normCount[i]); } } else { vnorms.ZeroCount(); vnorms.Resize(0); } }