SgMesh* MeshGenerator::generateExtrusion(const Extrusion& extrusion) { const int numSpines = extrusion.spine.size(); const int numCrosses = extrusion.crossSection.size(); bool isClosed = false; if(extrusion.spine[0][0] == extrusion.spine[numSpines - 1][0] && extrusion.spine[0][1] == extrusion.spine[numSpines - 1][1] && extrusion.spine[0][2] == extrusion.spine[numSpines - 1][2] ){ isClosed = true; } bool isCrossSectionClosed = (extrusion.crossSection[0] == extrusion.crossSection[numCrosses - 1]); SgMesh* mesh = new SgMesh; SgVertexArray& vertices = *mesh->setVertices(new SgVertexArray()); vertices.reserve(numSpines * numCrosses); Vector3 preZaxis(Vector3::Zero()); int definedZaxis = -1; vector<Vector3> Yaxisarray; vector<Vector3> Zaxisarray; if(numSpines > 2){ for(int i=0; i < numSpines; ++i){ Vector3 Yaxis, Zaxis; if(i == 0){ if(isClosed){ const Vector3& spine1 = extrusion.spine[numSpines - 2]; const Vector3& spine2 = extrusion.spine[0]; const Vector3& spine3 = extrusion.spine[1]; Yaxis = spine3 - spine1; Zaxis = (spine3 - spine2).cross(spine1 - spine2); } else { const Vector3& spine1 = extrusion.spine[0]; const Vector3& spine2 = extrusion.spine[1]; const Vector3& spine3 = extrusion.spine[2]; Yaxis = spine2 - spine1; Zaxis = (spine3 - spine2).cross(spine1 - spine2); } } else if(i == numSpines - 1){ if(isClosed){ const Vector3& spine1 = extrusion.spine[numSpines - 2]; const Vector3& spine2 = extrusion.spine[0]; const Vector3& spine3 = extrusion.spine[1]; Yaxis = spine3 - spine1; Zaxis = (spine3 - spine2).cross(spine1 - spine2); } else { const Vector3& spine1 = extrusion.spine[numSpines - 3]; const Vector3& spine2 = extrusion.spine[numSpines - 2]; const Vector3& spine3 = extrusion.spine[numSpines - 1]; Yaxis = spine3 - spine2; Zaxis = (spine3 - spine2).cross(spine1 - spine2); } } else { const Vector3& spine1 = extrusion.spine[i - 1]; const Vector3& spine2 = extrusion.spine[i]; const Vector3& spine3 = extrusion.spine[i + 1]; Yaxis = spine3 - spine1; Zaxis = (spine3-spine2).cross(spine1-spine2); } if(!Zaxis.norm()){ if(definedZaxis != -1) Zaxis = preZaxis; } else { if(definedZaxis == -1){ definedZaxis = i; } preZaxis = Zaxis; } Yaxisarray.push_back(Yaxis); Zaxisarray.push_back(Zaxis); } } else { const Vector3 Yaxis(extrusion.spine[1] - extrusion.spine[0]); Yaxisarray.push_back(Yaxis); Yaxisarray.push_back(Yaxis); } const int numScales = extrusion.scale.size(); const int numOrientations = extrusion.orientation.size(); Vector3 scale(1.0, 0.0, 1.0); AngleAxis orientation(0.0, Vector3::UnitZ()); for(int i=0; i < numSpines; ++i){ Matrix3 Scp; Vector3 y = Yaxisarray[i].normalized(); if(definedZaxis == -1){ AngleAxis R(acos(y[1]), Vector3(y[2], 0.0, -y[0])); Scp = R.toRotationMatrix(); } else { if(i < definedZaxis){ Zaxisarray[i] = Zaxisarray[definedZaxis]; } if(i && (Zaxisarray[i].dot(Zaxisarray[i - 1]) < 0.0)){ Zaxisarray[i] *= -1.0; } Vector3 z = Zaxisarray[i].normalized(); Vector3 x = y.cross(z); Scp << x, y, z; } const Vector3& spine = extrusion.spine[i]; if(numScales == 1){ scale << extrusion.scale[0][0], 0.0, extrusion.scale[0][1]; } else if(numScales > 1){ scale << extrusion.scale[i][0], 0.0, extrusion.scale[i][1]; } if(numOrientations == 1){ orientation = extrusion.orientation[0]; } else if(numOrientations > 1){ orientation = extrusion.orientation[i]; } for(int j=0; j < numCrosses; ++j){ const Vector3 crossSection(extrusion.crossSection[j][0], 0.0, extrusion.crossSection[j][1]); const Vector3 v1(crossSection[0] * scale[0], 0.0, crossSection[2] * scale[2]); const Vector3 v = Scp * orientation.toRotationMatrix() * v1 + spine; vertices.push_back(v.cast<float>()); } } for(int i=0; i < numSpines - 1 ; ++i){ const int upper = i * numCrosses; const int lower = (i + 1) * numCrosses; for(int j=0; j < numCrosses - 1; ++j) { mesh->addTriangle(j + upper, j + lower, (j + 1) + lower); mesh->addTriangle(j + upper, (j + 1) + lower, j + 1 + upper); } } int j = 0; if(isCrossSectionClosed){ j = 1; } Triangulator<SgVertexArray> triangulator; vector<int> polygon; if(extrusion.beginCap && !isClosed){ triangulator.setVertices(vertices); polygon.clear(); for(int i=0; i < numCrosses - j; ++i){ polygon.push_back(i); } triangulator.apply(polygon); const vector<int>& triangles = triangulator.triangles(); for(size_t i=0; i < triangles.size(); i += 3){ mesh->addTriangle(polygon[triangles[i]], polygon[triangles[i+1]], polygon[triangles[i+2]]); } } if(extrusion.endCap && !isClosed){ triangulator.setVertices(vertices); polygon.clear(); for(int i=0; i < numCrosses - j; ++i){ polygon.push_back(numCrosses * (numSpines - 1) + i); } triangulator.apply(polygon); const vector<int>& triangles = triangulator.triangles(); for(size_t i=0; i < triangles.size(); i +=3){ mesh->addTriangle(polygon[triangles[i]], polygon[triangles[i+2]], polygon[triangles[i+1]]); } } mesh->updateBoundingBox(); generateNormals(mesh, extrusion.creaseAngle); return mesh; }