コード例 #1
0
// Split the polygon into sets of unimonotone chains, and eventually call
// TriangulateMonotone() to convert them into triangles.
bool Triangulate(Vertex *first, Vertex *last, SkTDArray<SkPoint> *triangles) {
    DebugPrintf("Triangulate()\n");
    Vertex *currentVertex = first;
    while (!currentVertex->done()) {
        currentVertex->setDone(true);
        Vertex *bottomVertex = currentVertex->diagonal();
        if (bottomVertex != NULL) {
            Vertex *saveNext = currentVertex->next();
            Vertex *savePrev = bottomVertex->prev();
            currentVertex->setNext(bottomVertex);
            bottomVertex->setPrev(currentVertex);
            currentVertex->nullifyTrapezoid();
            bool success = Triangulate(bottomVertex, currentVertex, triangles);
            currentVertex->setDone(false);
            bottomVertex->setDone(false);
            currentVertex->setNext(saveNext);
            bottomVertex->setPrev(savePrev);
            bottomVertex->setNext(currentVertex);
            currentVertex->setPrev(bottomVertex);
            return Triangulate(currentVertex, bottomVertex, triangles)
                   && success;
        } else {
            currentVertex = currentVertex->next();
        }
    }
    return TriangulateMonotone(first, last, triangles);
}
コード例 #2
0
//Look at the GJK_EPA.h header file for documentation and instructions
bool SteerLib::GJK_EPA::intersect(float& return_penetration_depth, Util::Vector& return_penetration_vector, const std::vector<Util::Vector>& _shapeA, const std::vector<Util::Vector>& _shapeB)
{
	if (CONCAVE_POLYGONS)
		return Triangulate(_shapeA, _shapeB);
	
	std::vector<Util::Vector> _simplex;
	bool colliding;
	
	colliding = Triangulate(_shapeA, _shapeB);

	if (colliding)
	{
		EPA(return_penetration_depth, return_penetration_vector, _simplex, _shapeA, _shapeB);
		return true;
	}
	else
	{
		return_penetration_depth = 0;
		return_penetration_vector.zero();
		return false;
	}

	// To make compiler happy
	return false;
}
コード例 #3
0
/// returns triangle count
/// Any invalid vectors are ignored (they are delimiters for multiple polygons)
int CreateDelaunayTriangulation( cpVect *verts, int n_verts, cpVect *extraPoints, int pointCount, cpVect *triangles)
{
	int triangleCount;
	XYZ *p = new XYZ[n_verts + pointCount + 3];
	int count = 0;
	int i;
	for(i=0;i<n_verts;++i)
	{
		//if (verts[i].IsValid()) {
			p[count].x = verts[i].x;
			p[count].y = verts[i].y;
			++count;
		//}
	}
	for (;i<n_verts+pointCount;++i,++count)
	{
		p[count].x = extraPoints[i-n_verts].x;
		p[count].y = extraPoints[i-n_verts].y;
	}
	ITRIANGLE *v = new ITRIANGLE[3 * (pointCount + n_verts)];
	qsort(p, count, sizeof(XYZ), XYZCompare);

	Triangulate(count, p, v, triangleCount);

	for (int i=0;i<triangleCount;i++) {
		triangles[3*i] = cpv(p[v[i].p1].x,p[v[i].p1].y);
		triangles[3*i+1] = cpv(p[v[i].p2].x,	p[v[i].p2].y);
		triangles[3*i+2] = cpv(p[v[i].p3].x,	p[v[i].p3].y);
	}

	delete[] p;
	delete[] v;
	return triangleCount;
}	
コード例 #4
0
ファイル: Microphone.cpp プロジェクト: vrishe/3d-editor-08-a
void Microphone::setPrecision	(int prec) {
	precision = prec;

	delete [] micParts;
	micParts = new LPMESH3D[PARTS_NUM];
	Triangulate();
}
コード例 #5
0
ファイル: SQMAlgorithm.cpp プロジェクト: misop/BMM-Library
void SQMAlgorithm::triangulateOneRings2() {
	deque<SQMNode*> queue;
	if (root != NULL) queue.push_back(root);

	while (!queue.empty()) {
		SQMNode *node = queue.front();
		SQMNode *cycleNode = node->getCycleNode();
		queue.pop_front();

		if (node->getSQMNodeType() == SQMCycleLeaf && cycleNode != NULL) {
			//project stuff
			glm::vec3 normal = glm::normalize(cycleNode->getPosition_glm() - node->getPosition_glm());
			glm::vec3 origin = (cycleNode->getPosition_glm() + node->getPosition_glm())* 0.5f;
			node->projectOnPlaneRotateAndScale(mesh, origin, normal);
			cycleNode->projectOnPlaneRotateAndScale(mesh, origin, normal);
			//triangulate stuff
			vector<glm::vec3> *nodePoints = node->getCyclePoints();
			vector<glm::vec3> *cyclePoints = cycleNode->getCyclePoints();
			vector<glm::vec3> points;
			points.insert(points.end(), (*nodePoints).begin(), (*nodePoints).end());
			points.insert(points.end(), (*cyclePoints).begin(), (*cyclePoints).end());
			vector<glm::ivec3> triangles;
			Triangulate(points, triangles);
			//add triangles to mesh
			addTrianglesToMesh(node, cycleNode, triangles, (*nodePoints).size());
		}

		for (int i = 0; i < node->getNodes()->size(); i++) {
			queue.push_back((*node->getNodes())[i]);
		}
	}
}
コード例 #6
0
int ofxDelaunay::triangulate(){

    int nv = vertices.size();
	if (nv < 1) return 0; // crashes if try to triangulate 0 points

    //add 3 emptly slots, required by the Triangulate call
    vertices.push_back(XYZ());
    vertices.push_back(XYZ());
    vertices.push_back(XYZ());

    //allocate space for triangle indices
    triangles.resize(3*nv);

	int ntri;
	qsort( &vertices[0], vertices.size()-3, sizeof( XYZ ), XYZCompare );
	Triangulate( nv, &vertices[0], &triangles[0], ntri );

	// copy triangle data to ofxDelaunayTriangle.
	triangleMesh.clear();

    //copy vertices
	for (int i = 0; i < nv; i++){
        triangleMesh.addVertex(ofVec3f(vertices[i].x,vertices[i].y,vertices[i].z));
    }

    //copy triagles
	for(int i = 0; i < ntri; i++){
		triangleMesh.addIndex(triangles[ i ].p1);
		triangleMesh.addIndex(triangles[ i ].p2);
		triangleMesh.addIndex(triangles[ i ].p3);
	}

	return ntri;
}
コード例 #7
0
ファイル: ofxDelaunay.cpp プロジェクト: MartinHN/ofxDelaunay
int ofxDelaunay::triangulate(vector<int> *indices ){
    
    if(vertices.size() < 3){return NULL;}
    

	
	// make clone not to destroy vertices
  vector<XYZI> verticesTemp;
  if(indices!=nullptr){
    verticesTemp.resize(indices->size());
    int j = 0;
    for (auto & i:*indices){
      verticesTemp[j] = vertices[i];
      j++;
    }
  }
  else{verticesTemp=vertices;}
	qsort( &verticesTemp[0], verticesTemp.size(), sizeof( XYZI ), XYZICompare );
 int nv = verticesTemp.size();
	//vertices required for Triangulate
    vector<XYZ> verticesXYZ(nv);
	
	//copy XYZIs to XYZ
	for (int i = 0; i < nv; i++) {
		XYZ v;
		verticesXYZ[i].x = verticesTemp.at(i).x;
		verticesXYZ[i].y = verticesTemp.at(i).y;
		verticesXYZ[i].z = verticesTemp.at(i).z;
		
	}
	
    //add 3 emptly slots, required by the Triangulate call
    verticesXYZ.push_back(XYZ());
    verticesXYZ.push_back(XYZ());
    verticesXYZ.push_back(XYZ());
    
    //allocate space for triangle indices
    triangles.resize(3*nv);
    
	Triangulate( nv, &verticesXYZ[0], &triangles[0], ntri );


	//copy triangle data to ofxDelaunayTriangle.
	triangleMesh.clear();
	triangleMesh.setMode(OF_PRIMITIVE_TRIANGLES);
	
    //copy vertices
	for (int i = 0; i < vertices.size(); i++){
        triangleMesh.addVertex(ofVec3f(vertices[i].x,vertices[i].y,vertices[i].z));
    }
	
	//copy triangles
	for(int i = 0; i < ntri; i++){
		triangleMesh.addIndex(verticesTemp.at(triangles[ i ].p1).i);
		triangleMesh.addIndex(verticesTemp.at(triangles[ i ].p2).i);
		triangleMesh.addIndex(verticesTemp.at(triangles[ i ].p3).i);

  }
	return ntri;
}
コード例 #8
0
	void MakeDelaunay(const std::vector<float2>& vertexes, std::vector<uint3>& output)
	{
		output.clear();
		if (vertexes.size() < 3) {
			return;
		}
		int N = (int)vertexes.size();
		std::vector<std::pair<float2, int>> vertPairs(N);
		int index = 0;
		for (const float2& vert : vertexes) {
			vertPairs[index] = std::pair<float2, int>(vert, index);
			index++;
		}
		std::sort(vertPairs.begin(), vertPairs.end());
		std::vector<float2> tmp;
		tmp.reserve(vertPairs.size());
		for (std::pair<float2, int>& pr : vertPairs) {
			tmp.push_back(pr.first);
		}
		std::vector<int3>	cTriangles;
		Triangulate(tmp, cTriangles);
		for (int3& triangle : cTriangles) {
			if (triangle.x < N &&
				triangle.y < N &&
				triangle.z < N) {
				output.push_back(uint3((uint32_t)vertPairs[triangle.x].second, (uint32_t)vertPairs[triangle.y].second, vertPairs[triangle.z].second));
			}
		}
	}
コード例 #9
0
ファイル: Microphone.cpp プロジェクト: vrishe/3d-editor-08-a
Microphone::Microphone(unsigned char red, unsigned char green, unsigned char blue, 
						float br, 
						float bh,
						float bw,		
						float ur,		
						float uh,			
						float ug,			
						float hi,	
						float hr,		
						float hd,			
						float cr,		
						int prec
						) : clsMesh( MSH_MIC, red, green, blue ) {
	precision = prec;

	bR = br;
	bH = bh;
	bW = bw;

	uR = ur;
	uH = uh;
	uG = ug;
	hI = hi;

	hR = hr;
	hD = hd;
	cR = cr;

	tH = bH + uH + uG + hR;

	micParts = new LPMESH3D[PARTS_NUM];
	Triangulate();
}
コード例 #10
0
ファイル: SQMAlgorithm.cpp プロジェクト: misop/BMM-Library
void SQMAlgorithm::triangulateOneRings() {
	deque<SQMNode*> queue;
	if (root != NULL) queue.push_back(root);

	while (!queue.empty()) {
		SQMNode *node = queue.front();
		SQMNode *cycleNode = node->getCycleNode();
		queue.pop_front();

		if (node->getSQMNodeType() == SQMCycleLeaf && cycleNode != NULL) {
			vector<glm::vec3> *nodePoints = node->getCyclePoints();
			vector<glm::vec3> *cyclePoints = cycleNode->getCyclePoints();
			vector<glm::vec3> points;
			points.insert(points.end(), (*nodePoints).begin(), (*nodePoints).end());
			points.insert(points.end(), (*cyclePoints).begin(), (*cyclePoints).end());
			vector<glm::ivec3> triangles;
			Triangulate(points, triangles);
			addTrianglesToMesh(node, cycleNode, triangles, (*nodePoints).size());
		}

		for (int i = 0; i < node->getNodes()->size(); i++) {
			queue.push_back((*node->getNodes())[i]);
		}
	}
}
コード例 #11
0
ファイル: Polygon.cpp プロジェクト: Garfield-Chen/tng
vec Polygon::FastRandomPointInside(LCG &rng) const
{
	TriangleArray tris = Triangulate();
	if (tris.empty())
		return vec::nan;
	int i = rng.Int(0, (int)tris.size()-1);
	return TRIANGLE(tris[i]).RandomPointInside(rng);
}
コード例 #12
0
bool IsExtrinsicsPossible(const matf & P2, const TrackedPoint & point) {
  matf P1(3,4,0.0f); //TODO do not recreate each call
  P1(0,0) = P1(1,1) = P1(2,2) = 1.0f;
  matf p3d = Triangulate(P1, P2, point);

  //return p3d(2,0) >= 0;
  return IsInFront(P1, p3d) && IsInFront(P2, p3d); //TODO IsInFront(P1 ...) is trivial, since P1 is identity
}
コード例 #13
0
ファイル: tri.c プロジェクト: Bmcentee148/C-Programming
main()
{
   ReadVertices();
   PrintVertices();
   printf("%%Area of polygon = %g\n", 0.5 * AreaPoly2() );
   Triangulate();
   printf("showpage\n%%%%EOF\n");
}
コード例 #14
0
void CIdentityCube::Update(float)
{
    if (m_isDirty)
    {
        Triangulate();
        m_isDirty = false;
    }
}
コード例 #15
0
ファイル: Polygon.cpp プロジェクト: chengzg/MathGeoLib
float3 Polygon::FastRandomPointInside(LCG &rng) const
{
	std::vector<Triangle> tris = Triangulate();
	if (tris.empty())
		return float3::nan;
	int i = rng.Int(0, (int)tris.size()-1);
	return tris[i].RandomPointInside(rng);
}
コード例 #16
0
    void CacheGeometryHandler::Render()
    {
      if(Obj!=NULL){
	if(boolTriangulated==false)	Triangulate();
	Renderer->Render(Triangulator->getNumberOfPoints(),Triangulator->getNumberOfTriangles(),Triangulator->getTriangleVertices(),Triangulator->getTriangleFaces());
      }else if(ObjComp!=NULL){
	Renderer->Render(ObjComp);
      }
    }
コード例 #17
0
ファイル: ofxDelaunay.cpp プロジェクト: nosarious/ofxDelaunay
int ofxDelaunay::triangulate(){
    
    if(vertices.size() < 3){
        return NULL;
    }
    
    int nv = vertices.size();
	
	// make clone not to destroy vertices
	vector<XYZI> verticesTemp = vertices;
	qsort( &verticesTemp[0], verticesTemp.size(), sizeof( XYZI ), XYZICompare );
	
	//vertices required for Triangulate
    vector<XYZ> verticesXYZ;
	
	//copy XYZIs to XYZ
	for (int i = 0; i < nv; i++) {
		XYZ v;
		v.x = verticesTemp.at(i).x;
		v.y = verticesTemp.at(i).y;
		v.z = verticesTemp.at(i).z;
		verticesXYZ.push_back(v);
	}
	
    //add 3 emptly slots, required by the Triangulate call
    verticesXYZ.push_back(XYZ());
    verticesXYZ.push_back(XYZ());
    verticesXYZ.push_back(XYZ());
    
    //allocate space for triangle indices
    triangles.resize(3*nv);
    
	Triangulate( nv, &verticesXYZ[0], &triangles[0], ntri );
	
	//copy triangle data to ofxDelaunayTriangle.
	triangleMesh.clear();
	triangleMesh.setMode(OF_PRIMITIVE_TRIANGLES);
	
    //copy vertices
	for (int i = 0; i < nv; i++){
        triangleMesh.addVertex(ofVec3f(vertices[i].x,vertices[i].y,vertices[i].z));
    }
	
	//copy triangles
	for(int i = 0; i < ntri; i++){
		triangleMesh.addIndex(verticesTemp.at(triangles[ i ].p1).i);
		triangleMesh.addIndex(verticesTemp.at(triangles[ i ].p2).i);
		triangleMesh.addIndex(verticesTemp.at(triangles[ i ].p3).i);
	}
	
	//erase the last three triangles (missing code from original)
	vertices.erase(vertices.end()-1);
	vertices.erase(vertices.end()-1);
	vertices.erase(vertices.end()-1);
	
	return ntri;
}
コード例 #18
0
ファイル: Polygon.cpp プロジェクト: chengzg/MathGeoLib
bool Polygon::Intersects(const Capsule &capsule) const
{
	///@todo Optimize.
	std::vector<Triangle> tris = Triangulate();
	for(size_t i = 0; i < tris.size(); ++i)
		if (tris[i].Intersects(capsule))
			return true;

	return false;
}
コード例 #19
0
ファイル: Polygon.cpp プロジェクト: Garfield-Chen/tng
bool Polygon::Intersects(const Capsule &capsule) const
{
	///@todo Optimize.
	TriangleArray tris = Triangulate();
	for(size_t i = 0; i < tris.size(); ++i)
		if (TRIANGLE(tris[i]).Intersects(capsule))
			return true;

	return false;
}
コード例 #20
0
ファイル: ofxDelaunay.cpp プロジェクト: Joelone/FakeCaustics
int ofxDelaunay::triangulate(){
	XYZ *p_Temp = new XYZ[nv + 3]; 
	for (int i = 0; i < nv; i++)
		p_Temp[i] = p[i];      
	delete []p;
	p = p_Temp;
	v = new ITRIANGLE[3 * nv]; 
	qsort(p, nv, sizeof(XYZ), XYZCompare);
	Triangulate(nv, p, v, ntri);
	return ntri;
}
コード例 #21
0
matf TriangulateNonLinear(const matf & P1, const matf & P2, const TrackedPoint & p) {
  matf X(4,1);
  X(0,0) = p.x1;
  X(1,0) = p.y1;
  X(2,0) = p.x2;
  X(3,0) = p.y2;
  DistTriangulateNL dtnl(P1, P2);
  matf a_;
  LM(X, Triangulate(P1, P2, p), dtnl, a_);
  return a_;
}
コード例 #22
0
void UPaperSprite::BuildCustomCollisionData()
{
	// Rebuild the runtime geometry
	TArray<FVector2D> CollisionData;
	Triangulate(CollisionGeometry, CollisionData);

	// Adjust the collision data to be relative to the pivot
	for (int32 PointIndex = 0; PointIndex < CollisionData.Num(); ++PointIndex)
	{
		FVector2D& Point = CollisionData[PointIndex];
		Point = ConvertTextureSpaceToPivotSpace(Point);
	}

	// Bake it to the runtime structure
	switch (SpriteCollisionDomain)
	{
	case ESpriteCollisionMode::Use3DPhysics:
		{
			check(BodySetup3D);
			BodySetup3D->AggGeom.EmptyElements();

			//@TODO: Observe if the custom data is really a hand-edited bounding box, and generate box geom instead of convex geom!

			const FVector HalfThicknessVector = PaperAxisZ * 0.5f * CollisionThickness;
			//@TODO: Use this guy instead: DecomposeMeshToHulls
			//@TODO: Merge triangles that are convex together!
			int32 RunningIndex = 0;
			for (int32 TriIndex = 0; TriIndex < CollisionData.Num() / 3; ++TriIndex)
			{
				FKConvexElem& ConvexTri = *new (BodySetup3D->AggGeom.ConvexElems) FKConvexElem();
				ConvexTri.VertexData.Empty(6);
				for (int32 Index = 0; Index < 3; ++Index)
				{
					const FVector2D& Pos2D = CollisionData[RunningIndex++];
					
					const FVector Pos3D = (PaperAxisX * Pos2D.X) + (PaperAxisY * Pos2D.X);

					new (ConvexTri.VertexData) FVector(Pos3D - HalfThicknessVector);
					new (ConvexTri.VertexData) FVector(Pos3D + HalfThicknessVector);
				}
				ConvexTri.UpdateElemBox();
			}

			BodySetup3D->InvalidatePhysicsData();
			BodySetup3D->CreatePhysicsMeshes();
		}
		break;
	case ESpriteCollisionMode::Use2DPhysics:
		break;
	default:
		check(false);
		break;
	}
}
コード例 #23
0
//{CodeReview:Triangulation}
void Triangulate(std::vector<Polygon2D_t>& polygons, PolygonWinding winding, std::vector<const FVector2*>& triangles)
{
   std::vector<Polygon2D_t*> polygonsForHierarchy;
   polygonsForHierarchy.reserve(polygons.size());

   for (Polygon2D_t& polygon : polygons)
   {
      polygonsForHierarchy.push_back(&polygon);
   }

   PolygonHierarchy<Polygon2D_t> polygonHierarchy(polygonsForHierarchy, winding, Vec3D::ZAxis(), EarClipper::EXPERIMENTAL_TOLERANCE);

   std::queue< const PolygonHierarchy<Polygon2D_t>::Node* > polygonNodesToTriangulate;

   for (const std::unique_ptr<PolygonHierarchy<Polygon2D_t>::Node>& node : polygonHierarchy.Root()->children)
   {
      polygonNodesToTriangulate.push(node.get());
   }

   while (!polygonNodesToTriangulate.empty())
   {
      const PolygonHierarchy<Polygon2D_t>::Node* node = polygonNodesToTriangulate.front();
      polygonNodesToTriangulate.pop();

      std::size_t numChildren = node->children.size();

      if (numChildren == 0)
      {
         //The outer polygon is a simple polygon with no nested inner polygons
         Triangulate(*(node->polygon), triangles);
      }
      else
      {
         std::vector<const Polygon2D_t*> innerPolygons;
         innerPolygons.reserve(numChildren);

         //The outer polygon contains inner polygons
         for (const std::unique_ptr<PolygonHierarchy<Polygon2D_t>::Node>& child : node->children)
         {
            const PolygonHierarchy<Polygon2D_t>::Node* innerNode = child.get();
            innerPolygons.push_back(innerNode->polygon);

            for (const std::unique_ptr<PolygonHierarchy<Polygon2D_t>::Node>& grandChild : innerNode->children)
            {
               polygonNodesToTriangulate.push(grandChild.get());
            }
         }

         EarClipper(*(node->polygon), innerPolygons).Triangulate(triangles);
      }
   }
}
コード例 #24
0
    int*    CacheGeometryHandler::getTriangleFaces()
    {
      if(Obj!=NULL)
      {
	Obj->updateGeometryHandler();
	if(boolTriangulated==false)	Triangulate();
	return Triangulator->getTriangleFaces();
      }
      else
      {
	return NULL;
      }
    }
コード例 #25
0
    int CacheGeometryHandler::NumberOfPoints()
    {
      if(Obj!=NULL)
      {
	Obj->updateGeometryHandler();
	if(boolTriangulated==false)	Triangulate();
	return Triangulator->getNumberOfPoints();
      }
      else
      {
	return 0;
      }
    }
コード例 #26
0
bool SkConcaveToTriangles(size_t numPts,
                          const SkPoint pts[],
                          SkTDArray<SkPoint> *triangles) {
    DebugPrintf("SkConcaveToTriangles()\n");

    SkTDArray<Vertex> vertices;
    vertices.setCount(numPts);
    if (!ConvertPointsToVertices(numPts, pts, vertices.begin()))
        return false;

    triangles->setReserve(numPts);
    triangles->setCount(0);
    return Triangulate(vertices.begin(), vertices.end() - 1, triangles);
}
コード例 #27
0
ファイル: Microphone.cpp プロジェクト: vrishe/3d-editor-08-a
void Microphone::setTotalHeight	(float h) {
	tH = h;

	bH = tH * 0.061f;

	uH = tH * 0.58436f;
	uG = tH * 0.02057f;

	hR = tH * 0.165f;
	cR = tH * 0.12345679f;

	delete [] micParts;
	micParts = new LPMESH3D[PARTS_NUM];
	Triangulate();
}
コード例 #28
0
ファイル: Polygon.cpp プロジェクト: chengzg/MathGeoLib
float3 Polygon::ClosestPoint(const float3 &point) const
{
	assume(IsPlanar());

	std::vector<Triangle> tris = Triangulate();
	float3 closestPt = float3::nan;
	float closestDist = FLT_MAX;
	for(size_t i = 0; i < tris.size(); ++i)
	{
		float3 pt = tris[i].ClosestPoint(point);
		float d = pt.DistanceSq(point);
		if (d < closestDist)
		{
			closestPt = pt;
			closestDist = d;
		}
	}
	return closestPt;
}
コード例 #29
0
ファイル: Polygon.cpp プロジェクト: Garfield-Chen/tng
vec Polygon::ClosestPoint(const vec &point) const
{
	assume(IsPlanar());

	TriangleArray tris = Triangulate();
	vec closestPt = vec::nan;
	float closestDist = FLT_MAX;
	for(size_t i = 0; i < tris.size(); ++i)
	{
		vec pt = TRIANGLE(tris[i]).ClosestPoint(point);
		float d = pt.DistanceSq(point);
		if (d < closestDist)
		{
			closestPt = pt;
			closestDist = d;
		}
	}
	return closestPt;
}
コード例 #30
0
ファイル: Sphere.cpp プロジェクト: juj/MathGeoLib
void Sphere::Triangulate(VertexBuffer &vb, int numVertices, bool ccwIsFrontFacing) const
{
	Array<vec> position;
	Array<vec> normal;
	Array<float2> uv;
	position.Resize_unspecified(numVertices);
	normal.Resize_unspecified(numVertices);
	uv.Resize_unspecified(numVertices);
	Triangulate(position.ptr(), normal.ptr(), uv.ptr(), numVertices, ccwIsFrontFacing);
	int startIndex = vb.AppendVertices(numVertices);
	for(int i = 0; i < (int)position.size(); ++i)
	{
		vb.Set(startIndex+i, VDPosition, POINT_TO_FLOAT4(position[i]));
		if (vb.Declaration()->TypeOffset(VDNormal) >= 0)
			vb.Set(startIndex+i, VDNormal, DIR_TO_FLOAT4(normal[i]));
		if (vb.Declaration()->TypeOffset(VDUV) >= 0)
			vb.SetFloat2(startIndex+i, VDUV, 0, uv[i]);
	}
}