ContourPoint * MakeFLPoint(MeshVertex * v0, MeshVertex *v1, Mesh * mesh, const vec3 & cameraCenter, std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint *> & contourPoints) { std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint*>::iterator it = contourPoints.find(std::pair<MeshVertex*,MeshVertex*>(v0,v1)); if (it == contourPoints.end()) it = contourPoints.find(std::pair<MeshVertex*,MeshVertex*>(v1,v0)); if (it != contourPoints.end()) return (*it).second; // make the new vertex data. ContourPoint * flpt = new ContourPoint(); flpt->vertex = mesh->NewVertex(); ParamPointCC newPt; FindContour(v0->GetData().sourceLoc, v1->GetData().sourceLoc, cameraCenter, newPt); SetupVertex(flpt->vertex->GetData(), newPt, cameraCenter); flpt->vertex->GetData().facing = CONTOUR; // flpt->loc = newPt; flpt->sourceEdge = v0->GetEdge(v1); contourPoints.insert(std::pair<std::pair<MeshVertex*,MeshVertex*>,ContourPoint*> (std::pair<MeshVertex*,MeshVertex*>(v0,v1), flpt)); return flpt; }
// input can be a quad mesh (triangles ok?), output is a triangle mesh void FlowlineTesselate(Mesh * mesh, const vec3 & cameraCenter) { std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint* > contourPoints; std::vector<FlowLinePoint*> childPoints; std::multimap<MeshFace*,ContourPoint*> faceMap; std::set<MeshFace*> oldContourFaces; // each child point has a "stitchVertex" in the original mesh. some children might share them std::map<MeshVertex*,FlowLineCluster*> stitchVertices; // std::multimap<MeshVertex*, FlowLinePoint*> stitchToChildMap; // create contour vertices std::list<MeshFace*> inputFaces; mesh->GetFaces(inputFaces); std::vector<FaceRec> newFaces; // ------------------- create all the initial contour points -------------------- for(std::list<MeshFace*>::iterator it = inputFaces.begin(); it != inputFaces.end(); ++it) { ContourPoint * p[4]; MeshFace * face = *it; int numContourPoints = 0; int N = face->GetNumVertices(); assert(N ==3 || N == 4); for(int e=0; e<N; e++) { MeshVertex * v0 = face->GetVertex(e); MeshVertex * v1 = face->GetVertex((e+1)%N); assert(v0->GetData().facing != CONTOUR && v1->GetData().facing != CONTOUR); if (v0->GetData().facing == v1->GetData().facing) continue; ContourPoint * flpt = MakeFLPoint(v0,v1,mesh,cameraCenter,contourPoints); faceMap.insert(std::pair<MeshFace*,ContourPoint*>(face, flpt)); p[numContourPoints] = flpt; numContourPoints ++; } assert(numContourPoints == 0 || numContourPoints == 2 || numContourPoints == 4); // mark this as a contour face if (numContourPoints != 0) oldContourFaces.insert(face); if (numContourPoints == 4) printf("WARNING: QUAD FACE WITH TWO CONTOURS\n"); } // ---------------------- connect contour siblings ------------------- for(std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint* >::iterator it = contourPoints.begin(); it != contourPoints.end(); ++it) { ContourPoint * flpt = (*it).second; MeshEdge * edge = flpt->sourceEdge; assert(edge != NULL); // all contour points lie on edges MeshFace * adjFace[2] = { edge->GetLeftFace(), edge->GetRightFace() }; // connect to siblings for(int i=0; i<2; i++) if (adjFace[i] != NULL) { // assuming only 2 points per face for(std::multimap<MeshFace*,ContourPoint*>::iterator fit = faceMap.lower_bound(adjFace[i]); fit != faceMap.upper_bound(adjFace[i]); ++fit) if ( (*fit).second != flpt) flpt->AddSibling( (*fit).second); } } // ----------------------- create child points ---------------------------- for(std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint* >::iterator it = contourPoints.begin(); it != contourPoints.end(); ++it) { ContourPoint * flpt = (*it).second; // MeshEdge * edge = flpt->sourceEdge; // assert(edge != NULL); // all contour points lie on edges assert(flpt->nearChild == NULL && flpt->farChild == NULL); vec3 viewVec = cameraCenter - flpt->vertex->GetData().pos; // create two children // trace forward ParamRayCC nearRay = flpt->vertex->GetData().sourceLoc.VectorToParamRay(viewVec); ParamPointCC nearChildLoc = nearRay.Advance(); if (!nearChildLoc.IsNull() && nearChildLoc.IsEvaluable()) { // assert(nearChildLoc.IsValid()); flpt->nearChild = new FlowLinePoint(); flpt->nearChild->vertex = mesh->NewVertex(); // flpt->nearChild->loc = nearChildLoc; SetupVertex(flpt->nearChild->vertex->GetData(), nearChildLoc, cameraCenter); flpt->nearChild->parent = flpt; flpt->nearChild->sourceEdgeVV = nearChildLoc.SourceEdge(); childPoints.push_back(flpt->nearChild); assert(flpt->nearChild->vertex->GetData().facing != CONTOUR); } // do the same thing, tracing backward // trace backward ParamRayCC farRay = flpt->vertex->GetData().sourceLoc.VectorToParamRay(-viewVec); ParamPointCC farChildLoc = farRay.Advance(); if (!farChildLoc.IsNull() && farChildLoc.IsEvaluable()) { // assert(farChildLoc.IsValid()); flpt->farChild = new FlowLinePoint(); flpt->farChild->vertex = mesh->NewVertex(); // flpt->farChild->loc = farChildLoc; SetupVertex(flpt->farChild->vertex->GetData(), farChildLoc, cameraCenter); flpt->farChild->parent = flpt; flpt->nearChild->sourceEdgeVV = nearChildLoc.SourceEdge(); childPoints.push_back(flpt->farChild); assert(flpt->farChild->vertex->GetData().facing != CONTOUR); // flpt->farChild->sourceEdge = farChildLoc.SourceEdge(); } } // ----------------------- connect children to their siblings -------------------- for(std::vector<FlowLinePoint*>::iterator flit = childPoints.begin(); flit != childPoints.end(); ++flit) { FlowLinePoint * child = *flit; ContourPoint * parent = child->parent; for(int i=0; i<child->parent->NumSiblings(); i++) { ContourPoint * parentSib = parent->siblings[i]; FlowLinePoint * sib = (child == parent->nearChild ? parentSib->nearChild : parentSib->farChild); if (sib != NULL) child->AddSibling(sib); } } // ----------------- associate children with stitch vertices ------------------ for(std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint* >::iterator it = contourPoints.begin(); it != contourPoints.end(); ++it) { ContourPoint * flpt = (*it).second; MeshEdge * edge = flpt->sourceEdge; assert(edge != NULL); // all contour points lie on edges // check if we have a cusp // skip cusps and other weird cases for now if (flpt->nearChild == NULL || flpt->farChild == NULL || flpt->nearChild->vertex->GetData().facing == flpt->farChild->vertex->GetData().facing) continue; // find the front-facing/back-facing adjecent vertices of the source mesh to use as stitch vertices assert(edge->GetOrgVertex()->GetData().facing != edge->GetDestVertex()->GetData().facing); MeshVertex * frontVertex = NULL; MeshVertex * backVertex = NULL; if (edge->GetOrgVertex()->GetData().facing == FRONT) { frontVertex = edge->GetOrgVertex(); backVertex = edge->GetDestVertex(); } else { frontVertex = edge->GetDestVertex(); backVertex = edge->GetOrgVertex(); } flpt->nearChild->stitchTarget = (flpt->nearChild->vertex->GetData().facing == FRONT ? frontVertex : backVertex); flpt->farChild->stitchTarget = (flpt->farChild ->vertex->GetData().facing == FRONT ? frontVertex : backVertex); if (stitchVertices.find(flpt->nearChild->stitchTarget) == stitchVertices.end()) stitchVertices[flpt->nearChild->stitchTarget] = new FlowLineCluster(); FlowLineCluster * nearCluster = stitchVertices[flpt->nearChild->stitchTarget]; nearCluster->stitchVertex = flpt->nearChild->stitchTarget; nearCluster->parents.insert(flpt->nearChild); if (stitchVertices.find(flpt->farChild->stitchTarget) == stitchVertices.end()) stitchVertices[flpt->farChild->stitchTarget] = new FlowLineCluster(); FlowLineCluster * farCluster = stitchVertices[flpt->farChild->stitchTarget]; farCluster->stitchVertex = flpt->farChild->stitchTarget; farCluster->parents.insert(flpt->farChild); // stitchToChildMap.insert(std::pair<MeshVertex*, FlowLinePoint*>( flpt->nearChild->stitchTarget, flpt->nearChild)); // stitchToChildMap.insert(std::pair<MeshVertex*, FlowLinePoint*>( flpt->farChild->stitchTarget, flpt->farChild)); } // ----------------------- generate contour faces ----------------------------- printf("Num contour points = %d\n", (int)contourPoints.size()); for(std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint*>::iterator it = contourPoints.begin(); it != contourPoints.end(); ++it) { ContourPoint * flpt = (*it).second; for(int i =0; i<flpt->NumSiblings(); i++) { if (flpt->nearChild != NULL && flpt->siblings[i]->nearChild != NULL && flpt->nearChild->vertex->GetEdge(flpt->siblings[i]->nearChild->vertex) == NULL && flpt->siblings[i]->nearChild->vertex->GetEdge(flpt->nearChild->vertex) == NULL) // not already created MakeContourFaces(mesh, flpt, flpt->siblings[i], flpt->nearChild, flpt->siblings[i]->nearChild); if (flpt->farChild != NULL && flpt->siblings[i]->farChild != NULL && flpt->farChild->vertex->GetEdge(flpt->siblings[i]->farChild->vertex) == NULL && flpt->siblings[i]->farChild->vertex->GetEdge(flpt->farChild->vertex) == NULL) MakeContourFaces(mesh, flpt, flpt->siblings[i],flpt->farChild, flpt->siblings[i]->farChild); } } // -------------------- find the existing mesh vertices to be stitched to this cluster ------- for(std::map<MeshVertex*,FlowLineCluster*>::iterator it = stitchVertices.begin(); it != stitchVertices.end(); ++it) { MeshVertex * stitchVertex = (*it).first; FlowLineCluster * cluster = (*it).second; std::set<MeshFace*> oneRingFaces; GetOneRing(stitchVertex, oneRingFaces); for(std::set<MeshFace*>::iterator fit = oneRingFaces.begin(); fit != oneRingFaces.end(); ++fit) for(int i=0; i< (*fit)->GetNumVertices(); i++) { MeshVertex * v = (*fit)->GetVertex(i); if (v->GetData().facing == stitchVertex->GetData().facing && stitchVertices.find(v) == stitchVertices.end()) cluster->existingPoints.insert(v); } } // ---------------------- linearize parents of flowline clusters ------------ for(std::map<MeshVertex*,FlowLineCluster*>::iterator it = stitchVertices.begin(); it != stitchVertices.end(); ++it) { FlowLineCluster * cluster = (*it).second; std::set<FlowLinePoint*> remainingParents = cluster->parents; // copy the set of parents assert (remainingParents.size() > 0); FlowLinePoint * start = *(remainingParents.begin()); remainingParents.erase(remainingParents.begin()); cluster->parentsOrdered.push_back(start); for(int i=0; i<start->NumSiblings(); i++) { FlowLinePoint * next = start->siblings[i]; FlowLinePoint * last = start; while (remainingParents.find(next) != remainingParents.end()) { remainingParents.erase(remainingParents.find(next)); if (i == 0) cluster->parentsOrdered.push_back(next); else cluster->parentsOrdered.push_front(next); if (next->NumSiblings() > 1 && next->siblings[0] != last) next = next->siblings[0]; else if (next->NumSiblings() > 2 && next->siblings[1] != last) next = next->siblings[1]; else break; } } if (remainingParents.size() != 0) printf("CLUSTER WITH DISCONNECTED PARENTS\n"); else assert(cluster->parents.size() == cluster->parentsOrdered.size()); } // ---------------------- connect flowline clusters to siblings ------------- for(std::map<MeshVertex*,FlowLineCluster*>::iterator it = stitchVertices.begin(); it != stitchVertices.end(); ++it) { FlowLineCluster * cluster = (*it).second; // skip clusters with disconnected parents if (cluster->parents.size() != cluster->parentsOrdered.size()) continue; for(std::set<FlowLinePoint*>::iterator pit = cluster->parents.begin(); pit != cluster->parents.end(); ++pit) for(int i=0; i<(*pit)->NumSiblings(); ++i) { FlowLinePoint * sib = (*pit)->siblings[i]; if ( sib->stitchTarget != NULL && cluster->parents.find(sib) == cluster->parents.end() && !cluster->HasSibling(stitchVertices[sib->stitchTarget])) cluster->AddSibling(stitchVertices[sib->stitchTarget], *pit); } } // ----------------------- delete old contour/stitch faces ------------------------ // note: needed to keep the old faces around long enough for MakeContourFaces to use orientation and to mark the stitch faces std::set<MeshFace*> oldStitchFaces; for(std::set<MeshFace*>::iterator it = oldContourFaces.begin(); it != oldContourFaces.end(); ++it) for(int e=0; e<(*it)->GetNumVertices(); e++) { MeshFace * left = (*it)->GetEdge(e)->GetLeftFace(); MeshFace * right = (*it)->GetEdge(e)->GetRightFace(); if (left != (*it) && oldContourFaces.find(left) == oldContourFaces.end()) oldStitchFaces.insert(left); if (right != (*it) && oldContourFaces.find(right) == oldContourFaces.end()) oldStitchFaces.insert(right); } for(std::set<MeshFace*>::iterator it = oldContourFaces.begin(); it != oldContourFaces.end(); ++it) mesh->DeleteFace(*it); for(std::set<MeshFace*>::iterator fit = oldStitchFaces.begin(); fit != oldStitchFaces.end(); ++fit) if ( (*fit) != NULL) mesh->DeleteFace(*fit); // ---------------------- create connecting faces between flowline clusters ------ /* This part crashes printf("Creating cluster connecting faces\n"); std::set<std::pair<FlowLineCluster*,FlowLineCluster*> > visitedPairs; for(std::map<MeshVertex*,FlowLineCluster*>::iterator it = stitchVertices.begin(); it != stitchVertices.end(); ++it) { MeshVertex * stitchVertex = (*it).first; FlowLineCluster * cluster = (*it).second; for(int i=0;i<cluster->NumSiblings(); i++) { FlowLineCluster * sibling = cluster->siblings[i]; if (!sibling->HasSibling(cluster) || visitedPairs.find(std::pair<FlowLineCluster*,FlowLineCluster*>(sibling,cluster)) != visitedPairs.end()) continue; visitedPairs.insert(std::pair<FlowLineCluster*,FlowLineCluster*>(cluster,sibling)); int oppIndex = (sibling->siblings[0] == cluster ? 0 : 1); vector<MeshVertex*> intersection(cluster->existingPoints.size()); vector<MeshVertex*>::iterator vend; // find one or two existing points that these clusters share using a set intersection vend = std::set_intersection(cluster->existingPoints.begin(), cluster->existingPoints.end(), sibling->existingPoints.begin(), sibling->existingPoints.end(), intersection.begin()); // there should be 1 or 2 intersection points int intSize = int(vend - intersection.begin()); if (intSize == 0) // not sure this can happen; maybe at mesh boundaries or places where tracing went bad continue; // printf("intSize = %d\n", intSize); assert(sibling->endpoints[oppIndex]->vertex != cluster->endpoints[i]->vertex); if (intSize == 1) MakeFaceUnoriented(mesh, cluster->endpoints[i]->vertex, sibling->endpoints[oppIndex]->vertex, intersection[0]); else { assert(intSize == 2); MakeFaceUnoriented(mesh, cluster->endpoints[i]->vertex, sibling->endpoints[oppIndex]->vertex, intersection[0], intersection[1]); } } } // ----------------------- connect clusters to their own children ("existingPoints") ------------------------------ for(std::map<MeshVertex*,FlowLineCluster*>::iterator it = stitchVertices.begin(); it != stitchVertices.end(); ++it) { FlowLineCluster * cluster = (*it).second; if (cluster->existingPoints.size() == 0) // huh? continue; FlowLinePoint* parent = *(cluster->parentsOrdered.begin()); // make a list of children std::list<MeshVertex*> existingOrdered; // find a vertex adjacent to the first parent, but along a hole in the mesh. there should be only one... MeshVertex * child = NULL; std::list<MeshVertex*> oneRing; parent->vertex->GetSurroundingVertices(oneRing); for(std::list<MeshVertex*>::iterator it = oneRing.begin(); it != oneRing.end(); ++it) if ( ((*it)->GetEdge(parent->vertex)==NULL) != (parent->vertex->GetEdge(*it)==NULL) && cluster->existingPoints.find(*it) != cluster->existingPoints.end()) { child = *it; break; } while (child != NULL) { existingOrdered.push_back(child); cluster->existingPoints.erase(cluster->existingPoints.find(child)); MeshVertex * nextChild = NULL; oneRing.clear(); child->GetSurroundingVertices(oneRing); for(std::list<MeshVertex*>::iterator it = oneRing.begin(); it != oneRing.end();++it) if ( ((*it)->GetEdge(child)==NULL) != (child->GetEdge(*it)==NULL) && cluster->existingPoints.find(*it) != cluster->existingPoints.end()) { nextChild = *it; break; } child = nextChild; } // connect up pairs of child and parent into quads std::list<FlowLinePoint*>::iterator parentIt = cluster->parentsOrdered.begin(); std::list<FlowLinePoint*>::iterator nextParentIt; std::list<MeshVertex*>::iterator childIt = existingOrdered.begin(); std::list<MeshVertex*>::iterator nextChildIt; nextParentIt = parentIt; nextParentIt++; nextChildIt = childIt; nextChildIt++; while (nextParentIt != cluster->parentsOrdered.end() && nextChildIt != existingOrdered.end()) { MakeFaceUnoriented(mesh, (*parentIt)->vertex, (*nextParentIt)->vertex, *childIt, *nextChildIt); parentIt ++; nextParentIt++; childIt ++; nextChildIt++; } // make triangles from any leftovers while(nextParentIt != cluster->parentsOrdered.end()) { MakeFaceUnoriented(mesh, (*parentIt)->vertex, (*nextParentIt)->vertex, *childIt); parentIt ++; nextParentIt++; } while(nextChildIt != existingOrdered.end()) { MakeFaceUnoriented(mesh, *childIt, *nextChildIt, (*parentIt)->vertex); childIt ++; nextChildIt++; } } // ----------------------- connect gaps between stitch geometry and original --------------------- // TBD */ // ----------------------- convert all remaining quads to triangles ---------------------- printf("Converting quads to triangles\n"); std::list<MeshFace*> faces; mesh->GetFaces(faces); for(std::list<MeshFace*>::iterator it = faces.begin(); it != faces.end(); ++it) if ( (*it)->GetNumVertices() == 4) { MeshFace * face = *it; int vID1[3] = { face->GetVertex(0)->GetID(), face->GetVertex(1)->GetID(), face->GetVertex(2)->GetID() }; int vID2[3] = { face->GetVertex(0)->GetID(), face->GetVertex(2)->GetID(), face->GetVertex(3)->GetID() }; mesh->DeleteFace(face); NewFaceDebug(mesh, 3, vID1); NewFaceDebug(mesh, 3, vID2); } // ----------------------- create all new faces ---------------------- printf("Adding new faces\n"); for(std::vector<FaceRec>::iterator it = newFaces.begin(); it != newFaces.end(); ++it) { int IDs[3] = { (*it).v[0]->GetID(), (*it).v[1]->GetID(), (*it).v[2]->GetID() }; NewFaceDebug(mesh, 3, IDs); } }
BRUSH* ConvertXModelToBrushFormat ( char* szFilename, BRUSH* pBrush, int* piCount, LPDIRECT3DDEVICE8 lpDevice ) { // takes an x model and converts it into brushes // check the pointers are valid if ( !szFilename || !piCount ) return NULL; // used to access vertex data struct sMeshData { float x, y, z; float nx, ny, nz; float tu, tv; }; // variable declarations tagModelData* ptr; // model data LPDIRECT3DVERTEXBUFFER8 pMeshVertexBuffer; // vertex buffer LPDIRECT3DINDEXBUFFER8 pMeshIndexBuffer; // index buffer sMeshData* pMeshVertices; // mesh vertices WORD* pMeshIndices; // mesh indices sMesh* pMesh; // mesh data int iCount; // load the model Constructor ( lpDevice ); ptr = Load ( 1, szFilename ); pMesh = ptr->m_Object.m_Meshes; // count the number of brushes so we can allocate enough memory for them iCount = 0; while ( pMesh ) { pMesh = pMesh->m_Next; iCount++; } // store the number of models in the brush count pointer *piCount = iCount; // now setup the brushes pBrush = new BRUSH [ iCount ]; // allocate memory // set the mesh pointer back to the original mesh pMesh = ptr->m_Object.m_Meshes; // run through all meshes and store the brush data // first off set iCount to 0 so we know which brush // we are dealing with iCount = 0; while ( pMesh ) { int iInd = 0; DWORD dwNumVertices = pMesh->m_Mesh->GetNumVertices ( ); DWORD dwNumFaces = pMesh->m_Mesh->GetNumFaces ( ); pBrush [ iCount ].Faces = new POLYGON [ dwNumFaces ]; pBrush [ iCount ].FaceCount = dwNumFaces; pBrush [ iCount ].Bounds.Max = D3DXVECTOR3 ( 150.0f, 150.0f, 150.0f ); pBrush [ iCount ].Bounds.Min = D3DXVECTOR3 ( -150.0f, -150.0f, -150.0f ); pBrush [ iCount ].BSPTree = NULL; pMesh->m_Mesh->GetVertexBuffer ( &pMeshVertexBuffer ); pMesh->m_Mesh->GetIndexBuffer ( &pMeshIndexBuffer ); DWORD dwFVF = pMesh->m_Mesh->GetFVF ( ); pMeshVertexBuffer->Lock ( 0, pMesh->m_Mesh->GetNumVertices ( ) * sizeof ( sMeshData ), ( BYTE** ) &pMeshVertices, 0 ); pMeshIndexBuffer->Lock ( 0, 3 * pMesh->m_Mesh->GetNumFaces ( ) * sizeof ( WORD ), ( BYTE** ) &pMeshIndices, 0 ); for ( int iTemp = 0; iTemp < dwNumFaces; iTemp++ ) { char szX [ 256 ]; char szY [ 256 ]; char szZ [ 256 ]; int iA = pMeshIndices [ iInd + 0 ]; int iB = pMeshIndices [ iInd + 1 ]; int iC = pMeshIndices [ iInd + 2 ]; WORD wIndices [ ] = { 0, 1, 2 }; pBrush [ iCount ].Faces [ iTemp ].IndexCount = 3; pBrush [ iCount ].Faces [ iTemp ].TextureIndex = 0; pBrush [ iCount ].Faces [ iTemp ].VertexCount = 3; pBrush [ iCount ].Faces [ iTemp ].Indices = new WORD [ 3 ]; pBrush [ iCount ].Faces [ iTemp ].Vertices = new D3DVERTEX [ 3 ]; pBrush [ iCount ].Faces [ iTemp ].Vertices [ 0 ] = SetupVertex ( pMeshVertices [ iA ].x, pMeshVertices [ iA ].y, pMeshVertices [ iA ].z, pMeshVertices [ iA ].tu, pMeshVertices [ iA ].tv ); pBrush [ iCount ].Faces [ iTemp ].Vertices [ 1 ] = SetupVertex ( pMeshVertices [ iB ].x, pMeshVertices [ iB ].y, pMeshVertices [ iB ].z, pMeshVertices [ iB ].tu, pMeshVertices [ iB ].tv ); pBrush [ iCount ].Faces [ iTemp ].Vertices [ 2 ] = SetupVertex ( pMeshVertices [ iC ].x, pMeshVertices [ iC ].y, pMeshVertices [ iC ].z, pMeshVertices [ iC ].tu, pMeshVertices [ iC ].tv ); for ( int iChar = 0; iChar < 3; iChar++ ) { sprintf ( szX, "%.1f", pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].x ); sprintf ( szY, "%.1f", pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].y ); sprintf ( szZ, "%.1f", pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].z ); pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].x = atof ( szX ); pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].y = atof ( szY ); pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].z = atof ( szZ ); } memcpy ( pBrush [ iCount ].Faces [ iTemp ].Indices, wIndices, sizeof ( wIndices ) ); CalculateNormal ( &pBrush [ iCount ].Faces [ iTemp ] ); iInd += 3; } SetBlockPosition ( &pBrush [ iCount ], 0.0f, 0.0f, 0.0f, 1.0f ); pMeshVertexBuffer->Unlock ( ); pMeshIndexBuffer->Unlock ( ); iCount++; pMesh = pMesh->m_Next; } iCount = 0; pMesh = ptr->m_Object.m_Meshes; for ( int iTemp = ptr->m_Object.m_NumFrames; iTemp > 0; iTemp-- ) { sFrame* pFrame = ptr->m_Object.m_Frames->FindFrame ( iTemp ); if ( pFrame ) { pBrush [ iCount ].Matrix._41 = pFrame->m_matOriginal._41; pBrush [ iCount ].Matrix._42 = pFrame->m_matOriginal._42; pBrush [ iCount ].Matrix._43 = pFrame->m_matOriginal._43; iCount++; } } return pBrush; }