void Tessellate( NodeVector & vecNodes, FaceVector & vecFaces ) { int nInitialNodeListSize = vecNodes.size(); // Create centerpoint nodes for (int i = 0; i < vecFaces.size(); i++) { InsertQuadNodeCenter( vecNodes, vecNodes[vecFaces[i][0]], vecNodes[vecFaces[i][1]], vecNodes[vecFaces[i][2]], vecNodes[vecFaces[i][3]]); } // Construct tesselation SegmentMap mapSegment; ConstructSegmentMap(vecFaces, mapSegment, -1); vecFaces.clear(); SegmentMapIterator iter = mapSegment.begin(); for (; iter != mapSegment.end(); iter++) { Face faceNew = Face( iter->first[1], nInitialNodeListSize + iter->second[0], iter->first[0], nInitialNodeListSize + iter->second[1]); vecFaces.push_back(faceNew); } }
void LD3dsExporter::writeTriangle( VertexVector &vecVertices, FaceVector &vecFaces, const TCVector *points, int i0, int i1, int i2, int colorNumber, const TCFloat *matrix) { int ix[3]; int voffset = (int)vecVertices.size(); int foffset = (int)vecFaces.size(); ix[0] = i0; ix[1] = i1; ix[2] = i2; vecVertices.resize(vecVertices.size() + 3); vecFaces.resize(vecFaces.size() + 1); for (int i = 0; i < 3; i++) { TCVector vector = points[ix[i]]; vector = vector.transformPoint(matrix); vecVertices[voffset + i].v[0] = vector[0]; vecVertices[voffset + i].v[1] = vector[1]; vecVertices[voffset + i].v[2] = vector[2]; vecFaces[foffset].index[i] = (unsigned short)(voffset + i); vecFaces[foffset].material = getMaterial(colorNumber); } }
void Dual( Mesh & mesh ) { const int EdgeCountHexagon = 6; // Generate ReverseNodeArray mesh.ConstructReverseNodeArray(); // Backup Nodes and Faces NodeVector nodesOld = mesh.nodes; FaceVector facesOld = mesh.faces; mesh.nodes.clear(); mesh.faces.clear(); // Generate new Node array for (int i = 0; i < facesOld.size(); i++) { Node node; for (int j = 0; j < facesOld[i].edges.size(); j++) { node.x += nodesOld[facesOld[i][j]].x; node.y += nodesOld[facesOld[i][j]].y; node.z += nodesOld[facesOld[i][j]].z; } node.x /= static_cast<double>(facesOld[i].edges.size()); node.y /= static_cast<double>(facesOld[i].edges.size()); node.z /= static_cast<double>(facesOld[i].edges.size()); double dMag = node.Magnitude(); node.x /= dMag; node.y /= dMag; node.z /= dMag; mesh.nodes.push_back(node); } // Generate new Face array for (int i = 0; i < nodesOld.size(); i++) { const int nEdges = mesh.revnodearray[i].size(); Face face(EdgeCountHexagon); Face faceTemp(EdgeCountHexagon); int ixNode = 0; std::set<int>::const_iterator iter = mesh.revnodearray[i].begin(); for (; iter != mesh.revnodearray[i].end(); iter++) { faceTemp.SetNode(ixNode, *iter); ixNode++; } // Reorient Faces Node nodeCentral = nodesOld[i]; Node node0 = mesh.nodes[faceTemp[0]] - nodeCentral; Node nodeCross = CrossProduct(mesh.nodes[faceTemp[0]], nodeCentral); double dNode0Mag = node0.Magnitude(); // Determine the angles about the central Node of each Face Node std::vector<double> dAngles; dAngles.resize(faceTemp.edges.size()); dAngles[0] = 0.0; for (int j = 1; j < nEdges; j++) { Node nodeDiff = mesh.nodes[faceTemp[j]] - nodeCentral; double dNodeDiffMag = nodeDiff.Magnitude(); double dSide = DotProduct(nodeCross, nodeDiff); double dDotNorm = DotProduct(node0, nodeDiff) / (dNode0Mag * dNodeDiffMag); double dAngle; if (dDotNorm > 1.0) { dDotNorm = 1.0; } dAngles[j] = acos(dDotNorm); if (dSide > 0.0) { dAngles[j] = - dAngles[j] + 2.0 * M_PI; } } // Orient each Face by putting Nodes in order of increasing angle double dCurrentAngle = 0.0; face.SetNode(0, faceTemp[0]); for (int j = 1; j < nEdges; j++) { int ixNextNode = 1; double dNextAngle = 2.0 * M_PI; for (int k = 1; k < nEdges; k++) { if ((dAngles[k] > dCurrentAngle) && (dAngles[k] < dNextAngle)) { ixNextNode = k; dNextAngle = dAngles[k]; } } face.SetNode(j, faceTemp[ixNextNode]); dCurrentAngle = dNextAngle; } // Fill in missing edges for (int j = nEdges; j < EdgeCountHexagon; j++) { face.SetNode(j, face[nEdges-1]); } mesh.faces.push_back(face); } }
void GenerateFacesFromTriangle( int nRefineLevel, const MultiEdge & edge0, const MultiEdge & edge1, const MultiEdge & edge2, NodeVector & vecNodes, FaceVector & vecFaces ) { int i; int j; int k; int ixEndNode; int ixInt; // MultiEdges MultiEdge edgeBot; MultiEdge edgeMid; MultiEdge edgeTop; // Initial bottom edge edgeBot.push_back(edge0[0]); // Loop over all refined faces for (j = 0; j < nRefineLevel; j++) { // Generate top level vertices if (j == nRefineLevel-1) { edgeTop = edge2; } else { GenerateEdgeVertices( j+1, edge0[j+1], edge1[j+1], vecNodes, edgeTop); } // Generate faces for (i = 0; i < 2*j+1; i++) { // Downward pointing faces if (i % 2 == 0) { int ix = i/2; Face face(3); face.SetNode(0, edgeBot[ix]); face.SetNode(1, edgeTop[ix]); face.SetNode(2, edgeTop[ix+1]); vecFaces.push_back(face); // Upward pointing faces } else { int ix = (i-1)/2; Face face(3); face.SetNode(0, edgeTop[ix+1]); face.SetNode(1, edgeBot[ix+1]); face.SetNode(2, edgeBot[ix]); vecFaces.push_back(face); } } // New bottom edge edgeBot = edgeTop; } }
void RefineEverything( NodeVector & vecNodes, FaceVector & vecFaces, int nResolution ) { // Generate segment map SegmentMap mapSegment; ConstructSegmentMap(vecFaces, mapSegment, -1); FaceVector vecFacesOld = vecFaces; // Loop over all faces vecFaces.clear(); // Construct map from segments to edges std::map<Segment, Edge> mapEdge; SegmentMapIterator iter = mapSegment.begin(); for (; iter != mapSegment.end(); iter++) { Edge edge; GenerateEdgeVertices( nResolution, iter->first[0], iter->first[1], vecNodes, edge); mapEdge.insert(std::pair<Segment, Edge>(iter->first, edge)); } // Loop over all faces and refine for (int n = 0 ; n < vecFacesOld.size(); n++) { const Segment & seg0 = vecFacesOld[n].iterSegment[0]->first; const Segment & seg1 = vecFacesOld[n].iterSegment[1]->first; const Segment & seg2 = vecFacesOld[n].iterSegment[2]->first; const Segment & seg3 = vecFacesOld[n].iterSegment[3]->first; Edge edge0 = mapEdge.find(seg0)->second; Edge edge1 = mapEdge.find(seg1)->second; Edge edge3 = mapEdge.find(seg2)->second; Edge edge2 = mapEdge.find(seg3)->second; // Align bottom and left edge if (edge0[0] == edge1[0]) { } else if (edge0[0] == edge1[edge1.size()-1]) { edge1 = edge1.Flip(); } else if (edge0[edge0.size()-1] == edge1[0]) { edge0 = edge0.Flip(); } else if (edge0[edge0.size()-1] == edge1[edge1.size()-1]) { edge0 = edge0.Flip(); edge1 = edge1.Flip(); } else { _EXCEPTIONT("Logic error"); } // Align bottom and right edge if (edge0[edge0.size()-1] == edge2[0]) { } else if (edge0[edge0.size()-1] == edge2[edge2.size()-1]) { edge2 = edge2.Flip(); } else { _EXCEPTIONT("Logic error"); } // Align top and left edge if (edge1[edge1.size()-1] == edge3[0]) { } else if (edge1[edge1.size()-1] == edge3[edge3.size()-1]) { edge3 = edge3.Flip(); } else { _EXCEPTIONT("Logic error"); } Edge edgeTop; Edge edgeBot = edge0; for (int j = 0; j < nResolution; j++) { // Generate top level edge if (j != nResolution-1) { int ix0 = edge1[j+1]; int ix1 = edge2[j+1]; GenerateEdgeVertices(nResolution, ix0, ix1, vecNodes, edgeTop); } else { edgeTop = edge3; } // Generate face for (int i = 0; i < nResolution; i++) { Face face( edgeBot[i+1], edgeBot[i], edgeTop[i], edgeTop[i+1], vecFacesOld[n].nRefineLevel); face.nColor = vecFacesOld[n].nColor; face.nTag = vecFacesOld[n].nTag; vecFaces.push_back(face); } // Increment row edgeBot = edgeTop; } } }
void LD3dsExporter::doExport( LDLModel *pModel, Lib3dsNode *pParentNode, const TCFloat *matrix, int colorNumber, bool inPart, bool bfc, bool invert) { LDLFileLineArray *pFileLines = pModel->getFileLines(); if (pFileLines != NULL) { BFCState newBfcState = pModel->getBFCState(); int count = pModel->getActiveLineCount(); std::string meshName; Lib3dsMesh *pMesh = NULL; Lib3dsNode *pChildNode = NULL; // Lib3dsMeshInstanceNode *pInst; bool linesInvert = invert; bool isNew = false; if (TCVector::determinant(matrix) < 0.0f) { linesInvert = !linesInvert; } bfc = (bfc && newBfcState == BFCOnState) || newBfcState == BFCForcedOnState; meshName.resize(128); sprintf(&meshName[0], "m_%06d", ++m_meshCount); // meshName = getMeshName(pModel, pMesh); if (pMesh == NULL) { pMesh = lib3ds_mesh_new(meshName.c_str()); // memcpy(pMesh->matrix, matrix, sizeof(pMesh->matrix)); m_meshes[meshName] = pMesh; lib3ds_file_insert_mesh(m_file, pMesh, -1); isNew = true; } // pInst = lib3ds_node_new_mesh_instance(pMesh, // NULL/*(meshName + "n").c_str()*/, NULL, NULL, NULL); // pChildNode = (Lib3dsNode *)pInst; // memcpy(pChildNode->matrix, matrix, sizeof(float) * 16); // lib3ds_file_append_node(m_file, pChildNode, pParentNode); VertexVector vecVertices; FaceVector vecFaces; for (int i = 0; i < count; i++) { LDLFileLine *pFileLine = (*pFileLines)[i]; if (!pFileLine->isValid()) { continue; } switch (pFileLine->getLineType()) { case LDLLineTypeTriangle: case LDLLineTypeQuad: writeShapeLine(vecVertices, vecFaces, (LDLShapeLine *)pFileLine, matrix, colorNumber, bfc, linesInvert); break; case LDLLineTypeModel: { LDLModelLine *pModelLine = (LDLModelLine *)pFileLine; LDLModel *pOtherModel = pModelLine->getModel(true); if (pOtherModel != NULL) { TCFloat newMatrix[16]; int otherColorNumber = pModelLine->getColorNumber(); bool otherInPart = inPart; bool otherInvert = invert; if (pModelLine->getBFCInvert()) { otherInvert = !otherInvert; } if (otherColorNumber == 16) { otherColorNumber = colorNumber; } TCVector::multMatrix(matrix, pModelLine->getMatrix(), newMatrix); if (!inPart && pOtherModel->isPart() && m_seams) { TCVector min, max; TCFloat seamMatrix[16]; TCFloat tempMatrix[16]; pOtherModel->getBoundingBox(min, max); TCVector::calcScaleMatrix(m_seamWidth, seamMatrix, min, max); TCVector::multMatrix(newMatrix, seamMatrix, tempMatrix); memcpy(newMatrix, tempMatrix, sizeof(newMatrix)); otherInPart = true; } doExport(pOtherModel, pChildNode, newMatrix, otherColorNumber, otherInPart, bfc, otherInvert); } } break; default: // Get rid of warning break; } } if (isNew && vecVertices.size() > 0) { lib3ds_mesh_resize_vertices(pMesh, (int)vecVertices.size(), 0, 0); memcpy(pMesh->vertices, &vecVertices[0], sizeof(vecVertices[0]) * vecVertices.size()); lib3ds_mesh_resize_faces(pMesh, (int)vecFaces.size()); memcpy(pMesh->faces, &vecFaces[0], sizeof(vecFaces[0]) * vecFaces.size()); } else { --m_meshCount; } } }