int main(int argc, char *argv[]) { QApplication a(argc, argv); DrawingArea *area = new DrawingArea(); QPushButton *triangualteBut = new QPushButton(); triangualteBut->setText("Triangulate"); QVBoxLayout *lay = new QVBoxLayout(); lay->addWidget(area); //lay->addWidget(triangualteBut); QWidget window; window.setLayout(lay); window.show(); Triangulator *t = new Triangulator(area); QObject::connect(triangualteBut,SIGNAL(clicked()),t,SLOT(triangulate())); t->triangulate(); return a.exec(); }
void VRNature::addScrub(VRPolygonPtr area, bool addGround) { float a = area->computeArea(); if (a == 0) return; //VRTimer timer; timer.start(); //int t0 = timer.stop(); if (auto t = terrain.lock()) t->elevatePolygon(area, 0.18); Vec3d median = area->getBoundingBox().center(); area->translate(-median); for (auto p : area->getRandomPoints(1.0, -0.1, 0.7)) createRandomBush(median+p); if (addGround) { Triangulator tri; tri.add(*area); auto ground = tri.compute(); ground->translate(median); ground->setPositionalTexCoords(1.0, 0, Vec3i(0,2,1)); ground->updateNormals(); ground->flipNormals(); if (!groundPatches) { groundPatches = VRGeometry::create("groundPatches"); addChild( groundPatches ); VRTextureGenerator tg; tg.addSimpleNoise( Vec3i(128,128,1), false, Color4f(0.85,0.8,0.75,1), Color4f(0.5,0.3,0,1) ); auto mat = VRMaterial::create("earth"); mat->setTexture(tg.compose()); groundPatches->setMaterial(mat); } groundPatches->merge(ground, ground->getPose()); groundPatches->setPositionalTexCoords(1.0, 0, Vec3i(0,2,1)); // TODO: fix issues in VRGeoData } }
TriMeshRef makeMesh( const vector<PolyLine2f> &polys ) { Triangulator triangulator; for( vector<PolyLine2f>::const_iterator polyIt = polys.begin(); polyIt != polys.end(); ++polyIt ) triangulator.addPolyLine( *polyIt ); return make_shared<TriMesh>( triangulator.calcMesh() ); }
Bool ApplinkImporter::parseObjFile(char* path) { char line[256]; vector<string> stringArray; vector<string> subArray; ifstream fsImportObj; fsImportObj.open(path); if(!fsImportObj.is_open()){GePrint("File " + String(path) + " not found!");return false;} GePrint("Open file: " + String(path) + "."); long faceIndex = 0; int groupIndex = -1; // First group at 0 long pointIndex = 0; long texCoordIndex = 0; String matName; long idxMat = -1; StatusSetText("Parse file..."); while(!fsImportObj.eof()) { fsImportObj.getline(line, 255); //GePrint("row: " + String(buffer)); if(!strncmp("mtllib ", line, 7)) { char file[256]; sscanf(line, "mtllib %s", file); this->mtlFilePath = path; this->mtlFilePath.ClearSuffix(); this->mtlFilePath.SetFile(file); } else if(!strncmp("usemtl ", line, 7)) { String newMat; stringArray.clear(); istringstream iss(line); copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter<vector<string> >(stringArray)); newMat = stringArray[1].c_str(); bool inMats = false; for(unsigned int i = 0; i < this->matArray.size(); i++) { if(this->matArray[i].Name == newMat) { inMats = true; idxMat = i; break; } } if(!inMats) { this->matArray.resize(this->matArray.size() + 1); this->matArray[this->matArray.size() - 1].Name = newMat; idxMat = (long)this->matArray.size() - 1; } } else if(!strncmp("g ", line, 2)) { groupIndex++; faceIndex = 0; sscanf(line, "g %s", &groups[groupIndex].groupName); } else if(!strncmp("v ", line, 2)) { sscanf(line, "v %lf %lf %lf", &(verticies[pointIndex].x), &(verticies[pointIndex].y), &(verticies[pointIndex].z)); pointIndex++; } else if(!strncmp("vt", line, 2)) { sscanf(line, "vt %lf %lf", &(this->uvw[texCoordIndex].x), &(this->uvw[texCoordIndex].y)); sscanf(line, "vt %lf %lf %lf", &(this->uvw[texCoordIndex].x), &(this->uvw[texCoordIndex].y), &(this->uvw[texCoordIndex].z)); this->uvw[texCoordIndex].y = 1 - this->uvw[texCoordIndex].y; texCoordIndex++; } else if(!strncmp("f ", line, 2)) { if(idxMat != -1) { groups[groupIndex].polyMatIdx[faceIndex] = idxMat; } //GePrint("size: " + LongToString(sizeof(line))); stringArray.clear(); istringstream iss(line); copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter<vector<string> >(stringArray)); //GePrint("size: " + LongToString(stringArray.size())); subArray.clear(); int numFaces = (int)(stringArray.size() -1); if(numFaces == 3 || numFaces == 4) { for(UInt32 i = 1; i <= numFaces; i++) { subArray = this->Split(stringArray[i], '/'); for(UInt32 j=0; j < subArray.size(); j++) { string vIdx = subArray[j]; if(j==0)//position { groups[groupIndex].faces[faceIndex].vp[i-1] = atol(vIdx.c_str()) -1; } else if(j ==1 && vIdx != "")//tex coord { groups[groupIndex].faces[faceIndex].vt[i-1] = atol(vIdx.c_str()) - 1; } //Normals is not persent in this plugin. } } if(numFaces == 3)// this triangle, non quad. { groups[groupIndex].faces[faceIndex].vp[3] = atol(subArray[0].c_str()) - 1; if(subArray.size() > 1 && subArray[1] != "") { groups[groupIndex].faces[faceIndex].vt[3] = atol(subArray[1].c_str()) - 1; } } faceIndex++; } else// N-Gons { Triangulator* t = createTriangulator(); vector<UInt32> vpIdxs; vector<UInt32> vtIdxs; for(UInt32 j=1; j <= numFaces; j++) { subArray = this->Split(stringArray[j], '/'); UInt32 idx = atol(subArray[0].c_str()) -1; vpIdxs.push_back(idx); if(subArray[1] != "") { vtIdxs.push_back(atol(subArray[1].c_str()) -1); } t->addPoint(verticies[idx].x, verticies[idx].y, verticies[idx].z); } unsigned int tcount; unsigned int *indices = t->triangulate(tcount); for(UInt32 f = 0; f < tcount; f++) { for(UInt32 v=0; v < 4; v++) { UInt32 vv = 2-v; if(v == 3) vv = 0; groups[groupIndex].faces[faceIndex].vp[v] = vpIdxs[indices[f*3+vv]];//vp if(vpIdxs.size() > 0)//vt { groups[groupIndex].faces[faceIndex].vt[v] = vtIdxs[indices[f*3+vv]]; } } faceIndex++; //GePrint("Face3: " + LongToString(groups[groupIndex].faces[faceIndex].vp[0]) + ", " + LongToString(groups[groupIndex].faces[faceIndex].vp[1]) + ", " + LongToString(groups[groupIndex].faces[faceIndex].vp[2])); } releaseTriangulator(t); } } } fsImportObj.close(); return true; }
BaseObject *Objectify::GetVirtualObjects(BaseObject *op, HierarchyHelp *hh) { BaseDocument *doc = op->GetDocument(); BaseContainer *data = op->GetDataInstance(); BaseObject* obj = (BaseObject*)data->GetLink(CTT_OBJECT_LINK,doc,Obase); LONG crntFrame = doc->GetTime().GetFrame(doc->GetFps()); if (!obj) return NULL; if (obj->GetType() != Ospline){ return NULL; } // start new list op->NewDependenceList(); // check cache for validity and check master object for changes Bool dirty = op->CheckCache(hh) || op->IsDirty(DIRTYFLAGS_DATA); // if child list has been modified if (!dirty) dirty = !op->CompareDependenceList(); // mark child objects as processed op->TouchDependenceList(); dirty = dirty || (prevFrame != crntFrame); prevFrame = crntFrame; // if no change has been detected, return original cache if (!dirty) return op->GetCache(hh); SplineObject* spline = (SplineObject*) obj; AutoAlloc<SplineHelp> splineHelp; StatusSetText("Collecting points"); float positioAlongSpline = data->GetReal(POSITION_ALONG_SPLINE,0.5); positioAlongSpline /= 10000.0f; positioAlongSpline = positioAlongSpline > 1.0 ? 1.0: positioAlongSpline; positioAlongSpline = positioAlongSpline < 0.0 ? 0.0: positioAlongSpline; cout<<positioAlongSpline<<endl; vector<vector<float> > points; for (LONG i = 0; i < spline->GetSegmentCount(); i++){ Vector p = spline->GetSplinePoint(positioAlongSpline, i); vector<float> point; point.push_back(p.x); point.push_back(p.y); point.push_back(p.z); points.push_back(point); } StatusSetText("Collected "+LongToString(points.size())+" points"); ksearchNeighbors= data->GetLong(TRIANGULATION_MAX_NEIGHBORS, 100); gp3SearchRadius = data->GetReal(TRIANGULATION_MAX_SEARCH_RADIUS,30.); gp3MaxNeighbors = data->GetLong(KSEARCH_NEIGHBORS, 20); gp3Mu = data->GetReal(KSEARCH_MU, 0.5); vector<vector<float> > surfacePoints; vector<vector<int> > triIndxs; StatusSetBar(0); StatusSetText("Triangulating"); bool useMls = data->GetBool(USE_MLS, false); tri.computeSurface(points, surfacePoints, triIndxs, ksearchNeighbors, gp3SearchRadius, gp3MaxNeighbors, gp3Mu, useMls); StatusSetBar(100); StatusSetText("Got "+LongToString(triIndxs.size())+" triangles"); if (triIndxs.size() == 0){ return NULL; } PolygonObject* myPoly = PolygonObject::Alloc(surfacePoints.size(),triIndxs.size()); Vector* ppoints = myPoly->GetPointW(); vector<float> sp; for (int t = 0; t < surfacePoints.size()-2; t += 3) { sp = surfacePoints[t]; ppoints[t+0] = Vector(sp[0],sp[1],sp[2]); sp = surfacePoints[t+1]; ppoints[t+1] = Vector(sp[0],sp[1],sp[2]); sp = surfacePoints[t+2]; ppoints[t+2] = Vector(sp[0],sp[1],sp[2]); } for (int t = 0; t < triIndxs.size(); t ++) { myPoly->GetPolygonW()[t] = CPolygon(triIndxs[t][0], triIndxs[t][1], triIndxs[t][2], triIndxs[t][2]); } StatusClear(); myPoly->Message(MSG_UPDATE); return ToPoly(myPoly); BaseThread* bt=hh->GetThread(); BaseObject* main = BaseObject::Alloc(Onull); SplineObject* emptySpline = SplineObject::Alloc(0, SPLINETYPE_LINEAR); ModelingCommandData mcd; mcd.doc = doc; mcd.op = emptySpline; if(!SendModelingCommand(MCOMMAND_JOIN, mcd)){ return NULL; } Error: return NULL; }
int main( int argc, const char* argv[] ) { double max_area; double min_angle; po::options_description po_desc( "Allowed options" ); po_desc.add_options() ( "help", "produce help message" ) ( "max-size,s", po::value<double>( &max_area )->default_value( 0.01 ), "set the maximum triangle area for the refinement algorithm" ) ( "min-angle,a", po::value<double>( &min_angle )->default_value( 21 ), "set the minimum angle for the refinement algorithm" ) ( "input-file", po::value<std::string>(), "input file describing the polygonal boundary (in Well-Known Text format)"); po::positional_options_description po_pdesc; po_pdesc.add("input-file", -1); po::variables_map po_vm; po::store( po::command_line_parser( argc, argv ).options( po_desc ).positional( po_pdesc ).run(), po_vm ); po::notify( po_vm ); if ( po_vm.count( "help" ) ) { std::cout << po_desc << std::endl; return EXIT_SUCCESS; } if ( ! po_vm.count( "input-file" ) ) { std::cout << "Name of the input file not specified\n"; std::cout << po_desc << std::endl; return EXIT_FAILURE; } std::cout << "Parameters used:" << std::endl << " maximum triangle area = " << max_area << std::endl << " minimum angle = " << min_angle << std::endl; try { Polygon boundary; read_polygon( po_vm["input-file"].as< std::string >(), boundary ); Mesh mesh; Triangulator<Mesh> triangulator; triangulator.triangulate( boundary, mesh ); io::write_eps( "mesh_1.eps", mesh ); mesh.make_cdt(); io::write_eps( "mesh_2.eps", mesh ); Mesher mesher; mesher.refine( mesh, max_area, min_angle ); io::write_eps( "mesh_3.eps", mesh ); io::write_stl( "mesh_3.stl", mesh ); io::write_off( "mesh_3.off", mesh ); io::write_obj( "mesh_3.obj", mesh ); io::write_ply( "mesh_3.ply", mesh ); Relax relax; relax.relax( mesh ); io::write_eps( "mesh_4.eps", mesh ); // smoother smooth; // smooth.smooth(m, 1); // Postscript_stream ps5("mesh_5.eps", m.bounding_box()); // ps5 << m; // // code does not pass a debug assert: // meshgen.refine(0.0001000, 25); // Postscript_stream ps6("mesh_6.eps", m.bounding_box()); // ps6 << m; // // smooth.smooth(m, 5); // // Postscript_stream ps7("mesh_7.eps", m.bounding_box()); // // ps7 << m; std::cout << "Final mesh:" << std::endl << " # nodes: " << mesh.number_of_nodes() << std::endl << " # edges: " << mesh.number_of_edges() << std::endl << " # faces: " << mesh.number_of_faces() << std::endl; } catch ( boost::exception& e ) { std::cerr << boost::diagnostic_information( e ); } return EXIT_SUCCESS; }
void VRNature::addGrassPatch(VRPolygonPtr Area, bool updateLODs, bool addGround) { // TODO: needs optimizations! //VRTimer timer; timer.start(); //int t0 = timer.stop(); //cout << "VRNature::addGrassPatch " << t0 << endl; int i=0; auto ground = VRGeometry::create("ground"); float a = Area->computeArea(); if (a == 0) return; //cout << "VRNature::addGrassPatch " << a << endl; map<VRLodLeafPtr, bool> toUpdate; for (auto area : Area->gridSplit(10.0)) { if (area->isCCW()) area->reverseOrder(); //cout << " sub Area " << i << " " << timer.stop() - t0 << endl; if (auto t = terrain.lock()) t->elevatePolygon(area, 0.18); Vec3d median = area->getBoundingBox().center(); area->translate(-median); //cout << " A1 " << timer.stop() - t0 << endl; auto grass = VRGrassPatch::create(); grass->addAttachment("grass", 0); grass->setArea(area); //cout << " A2 " << timer.stop() - t0 << endl; grassPatchRefs[grass.get()] = grass; auto leaf = lodTree->addObject(grass, median, 0); // pose contains the world position! grass->setWorldPosition(median); toUpdate[leaf] = true; //cout << " A3 " << timer.stop() - t0 << endl; //cout << " VRNature::addGrassPatch " << median << " " << area->computeArea() << endl; if (addGround) { Triangulator tri; tri.add(*area); auto geo = tri.compute(); geo->translate(median); ground->merge(geo); } i++; } if (updateLODs) for (auto l : toUpdate) computeLODs(l.first); if (addGround) { VRTextureGenerator tg; tg.addSimpleNoise( Vec3i(128,128,1), true, Color4f(0.85,0.8,0.75,1), Color4f(0.5,0.3,0,1) ); auto mat = VRMaterial::create("earth"); mat->setTexture(tg.compose()); mat->clearTransparency(); ground->setPositionalTexCoords(1.0, 0, Vec3i(0,2,1)); //addChild(ground); if (!grassGroundPatches) { grassGroundPatches = VRGeometry::create("grassGroundPatches"); addChild( grassGroundPatches ); grassGroundPatches->setMaterial(mat); } grassGroundPatches->merge(ground); } }
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; }
//----------------------------------------------------------------------- void Extruder::_extrudeCapImpl(TriangleBuffer& buffer) const { std::vector<int> indexBuffer; PointList pointList; buffer.rebaseOffset(); Triangulator t; if (mShapeToExtrude) t.setShapeToTriangulate(mShapeToExtrude); else t.setMultiShapeToTriangulate(mMultiShapeToExtrude); t.triangulate(indexBuffer, pointList); buffer.estimateIndexCount(2*indexBuffer.size()); buffer.estimateVertexCount(2*pointList.size()); //begin cap buffer.rebaseOffset(); Quaternion qBegin = Utils::_computeQuaternion(mExtrusionPath->getDirectionAfter(0)); if (mRotationTrack) { Real angle = mRotationTrack->getFirstValue(); qBegin = qBegin*Quaternion((Radian)angle, Vector3::UNIT_Z); } Real scaleBegin=1.; if (mScaleTrack) scaleBegin = mScaleTrack->getFirstValue(); for (size_t j =0;j<pointList.size();j++) { Vector2 vp2 = pointList[j]; Vector3 vp(vp2.x, vp2.y, 0); Vector3 normal = -Vector3::UNIT_Z; Vector3 newPoint = mExtrusionPath->getPoint(0)+qBegin*(scaleBegin*vp); addPoint(buffer, newPoint, qBegin*normal, vp2); } for (size_t i=0;i<indexBuffer.size()/3;i++) { buffer.index(indexBuffer[i*3]); buffer.index(indexBuffer[i*3+2]); buffer.index(indexBuffer[i*3+1]); } // end cap buffer.rebaseOffset(); Quaternion qEnd = Utils::_computeQuaternion(mExtrusionPath->getDirectionBefore(mExtrusionPath->getSegCount())); if (mRotationTrack) { Real angle = mRotationTrack->getLastValue(); qEnd = qEnd*Quaternion((Radian)angle, Vector3::UNIT_Z); } Real scaleEnd=1.; if (mScaleTrack) scaleEnd = mScaleTrack->getLastValue(); for (size_t j =0;j<pointList.size();j++) { Vector2 vp2 = pointList[j]; Vector3 vp(vp2.x, vp2.y, 0); Vector3 normal = Vector3::UNIT_Z; Vector3 newPoint = mExtrusionPath->getPoint(mExtrusionPath->getSegCount())+qEnd*(scaleEnd*vp); addPoint(buffer, newPoint, qEnd*normal, vp2); } for (size_t i=0;i<indexBuffer.size()/3;i++) { buffer.index(indexBuffer[i*3]); buffer.index(indexBuffer[i*3+1]); buffer.index(indexBuffer[i*3+2]); } }
//----------------------------------------------------------------------- void Lathe::_latheCapImpl(TriangleBuffer& buffer) const { std::vector<int> indexBuffer; PointList pointList; buffer.rebaseOffset(); Triangulator t; Shape shapeCopy; MultiShape multishapeCopy; if (mShapeToExtrude) { shapeCopy = *mShapeToExtrude; shapeCopy.close(); t.setShapeToTriangulate(&shapeCopy); } else { multishapeCopy = *mMultiShapeToExtrude; multishapeCopy.close(); t.setMultiShapeToTriangulate(mMultiShapeToExtrude); } t.triangulate(indexBuffer, pointList); buffer.estimateIndexCount(2*indexBuffer.size()); buffer.estimateVertexCount(2*pointList.size()); //begin cap buffer.rebaseOffset(); Quaternion q; q.FromAngleAxis(mAngleBegin, Vector3::UNIT_Y); for (size_t j =0;j<pointList.size();j++) { Vector2 vp2 = pointList[j]; Vector3 vp(vp2.x, vp2.y, 0); Vector3 normal = Vector3::UNIT_Z; addPoint(buffer, q*vp, q*normal, vp2); } for (size_t i=0;i<indexBuffer.size()/3;i++) { buffer.index(indexBuffer[i*3]); buffer.index(indexBuffer[i*3+1]); buffer.index(indexBuffer[i*3+2]); } //end cap buffer.rebaseOffset(); q.FromAngleAxis(mAngleEnd, Vector3::UNIT_Y); for (size_t j =0;j<pointList.size();j++) { Vector2 vp2 = pointList[j]; Vector3 vp(vp2.x, vp2.y, 0); Vector3 normal = -Vector3::UNIT_Z; addPoint(buffer, q*vp, q*normal, vp2); } for (size_t i=0;i<indexBuffer.size()/3;i++) { buffer.index(indexBuffer[i*3]); buffer.index(indexBuffer[i*3+2]); buffer.index(indexBuffer[i*3+1]); } }