/**
 * \brief Transform from current triangle to the target triangle
 */
Transform	Triangle::to(const Triangle& target) const {
	double	rotation = rotate_to(target);
	double	scale = scale_to(target);
	Transform	result(rotation, Point(), scale);
	Point	translation = target.basepoint() - result(basepoint());
	result = result + translation;
	return result;
}
std::pair<PointCGAL,PointCGAL> getMeshBoundingBox(MeshData &meshData)
{
	std::list<Triangle> meshTriangles = meshData.first;
	std::list<PointCGAL> pointsInMesh;
	std::list<Triangle>::iterator triangleIter;
	for(triangleIter = meshTriangles.begin(); triangleIter != meshTriangles.end(); ++triangleIter)
	{
		Triangle t = *triangleIter;
		pointsInMesh.push_back(t.vertex(0));
		pointsInMesh.push_back(t.vertex(1));
		pointsInMesh.push_back(t.vertex(2));
	}

	Kernel::Iso_cuboid_3 isoCuboid = CGAL::bounding_box(pointsInMesh.begin(), pointsInMesh.end());

	return std::pair<PointCGAL,PointCGAL>(isoCuboid.min(), isoCuboid.max());
}
BaseBuilding::BaseBuilding(const Triangle& t, const unsigned int& typeCentre, const double& heightMax)
{
	listPoints.push_back(t[0]);
	listPoints.push_back(t[1]);
	listPoints.push_back(t[2]);
	airMin = t.Area()*0.3;
	setBuildingInfo(typeCentre, heightMax);
}
Example #4
0
int main(void)
{
   Rectangle Rect;
   Triangle  Tri;

   Rect.setWidth(5);
   Rect.setHeight(7);
   // Print the area of the object.
   cout << "Total Rectangle area: " << Rect.getArea() << endl;

   Tri.setWidth(5);
   Tri.setHeight(7);
   // Print the area of the object.
   cout << "Total Triangle area: " << Tri.getArea() << endl;

   return 0;
}
Example #5
0
int main(){
	
	double x1,y1,x2,y2,x3,y3;

    const double pi = acos(-1);

    while ( scanf("%lf %lf %lf %lf %lf %lf", &x1,&y1,&x2,&y2,&x3,&y3) != EOF ){

        Triangle t = Triangle(Point(x1,y1),Point(x2,y2),Point(x3,y3));

        double circun = 2.0 *  t.circumradius() * pi;

        printf("%.2lf\n", circun);
    }

	return 0;
}
Batiment::Batiment(const Triangle& t, const unsigned int& typeCentre, const double& hauteurMax)
{
	listePoints.push_back(t[0]);
	listePoints.push_back(t[1]);
	listePoints.push_back(t[2]);
	airMin = t.Area()*0.3;
	setBatimentInfos(typeCentre, hauteurMax);
}
Example #7
0
// the function for finding the intersection point between traingle and ray
// Solve the equation: t = -(Po . N + d) / (V . N) and P = Po + tV
Point findIntersection(Point init , Point v , Triangle triangle){
  
  Point p1 = triangle.getX();
  Point p2 = triangle.getY();
  Point p3 = triangle.getZ();
  
  Point p12 = pointDifference(p1,p2);
  Point p13 = pointDifference(p1,p3);
    
  Point normal = crossProduct(p12 , p13);
  
  double t = (normal.getX() * p1.getX() + normal.getY() * p1.getY() + normal.getZ() * p1.getZ() - normal.getX() * init.getX() - normal.getY() * init.getY() - normal.getZ() * init.getZ())/(normal.getX()*v.getX() + normal.getY() * v.getY() + normal.getZ() * v.getZ());
  
  Point result( init.getX() + t * v.getX() , init.getY() + t * v.getY() , init.getZ() + t * v.getZ() ); 
  
  return result;
}
Example #8
0
Triangle gen_pseudo_random() {
	int k;
	long long t, mod;
	Triangle r;
	
	//Init
	t = 0;
	mod = 1048576;
	
	for(k = 1; k <= 500500; k++) {
		t = (615949 * t + 797807) % mod;
		
		r.push_back(t - 524288);
	}
	
	return r;
}
Example #9
0
	QModelIndex cast( NifModel * nif, const QModelIndex & index )
	{
		if ( nif->isArray( index ) )
		{
			QVector<Triangle> tris = nif->getArray<Triangle>( index );
			for ( int t = 0; t < tris.count(); t++ )
				tris[t].flip();
			nif->setArray<Triangle>( index, tris );
		}
		else
		{
			Triangle t = nif->get<Triangle>( index );
			t.flip();
			nif->set<Triangle>( index, t );
		}
		return index;
	}
Example #10
0
int main(int argc, char *argv[]) {
    // GLFW Initialization
    if(!glfwInit()) {
        fprintf(stderr, "Failed to initialize GLFW\n");
        return EXIT_FAILURE;
    }

    glfwSetErrorCallback(ErrorCallback);

    // hint GLFW that we would like an OpenGL 3 context (at least)
    // http://www.glfw.org/faq.html#how-do-i-create-an-opengl-30-context
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    // attempt to open the window: fails if required version unavailable
    // note some Intel GPUs do not support OpenGL 3.2
    // note update the driver of your graphic card
    GLFWwindow* window = glfwCreateWindow(512, 512, "spiral", NULL, NULL);
    if(!window) {
        glfwTerminate();
        return EXIT_FAILURE;
    }

    // makes the OpenGL context of window current on the calling thread
    glfwMakeContextCurrent(window);

    // set the callback for escape key
    glfwSetKeyCallback(window, KeyCallback);

    // GLEW Initialization (must have a context)
    // https://www.opengl.org/wiki/OpenGL_Loading_Library
    glewExperimental = GL_TRUE; // fixes glew error (see above link)
    if(glewInit() != GLEW_NO_ERROR) {
        fprintf( stderr, "Failed to initialize GLEW\n");
        return EXIT_FAILURE;
    }

    cout << "OpenGL" << glGetString(GL_VERSION) << endl;

    // initialize our OpenGL program
    Init();

    // render loop
    while(!glfwWindowShouldClose(window)) {
        Display();
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    triangle.Cleanup();

    // close OpenGL window and terminate GLFW
    glfwDestroyWindow(window);
    glfwTerminate();
    return EXIT_SUCCESS;
}
bool isTriangleInTriangle(Triangle& trig1, Triangle& trig2) 
{
	if(trig1.isPointInsideFigure(trig2.getFstEdge()) && trig1.isPointInsideFigure(trig2.getSndEdge()) && trig1.isPointInsideFigure(trig2.getThrdEdge()))
		return true;
		
	if(trig2.isPointInsideFigure(trig1.getFstEdge()) && trig2.isPointInsideFigure(trig1.getSndEdge()) && trig2.isPointInsideFigure(trig1.getThrdEdge()))
		return true;
		
	return false;
}
Example #12
0
void FractureObject::ExpandComponent(FractureComponent * comp, Triangle * start)
{
    std::queue<Triangle *> procList;
    procList.push(start);

    while(procList.size() > 0) {
        //Pop the next triangle from the queue
        Triangle * t = procList.front(); procList.pop();
        //Check that its still valid(not visited) and if so, add to component
        //and indicate that its visited
        if(t->IsVisited())
            continue;
        comp->AddTriangle(t);
        t->SetIsVisited(true);
        t->SetFractureGroup(comp->compId);

        //Now check to see if it can add any of its neighbors
        for(unsigned int i = 0; i < 3; i++) {
            //Check that there's a triangle adjacent to this and that the edge is not
            //a fracture edge
            if(t->GetEdge(i)->GetRefCount() > 1 &&
                t->GetEdge(i)->IsFracture() == false) {
                    //(t->GetEdge(i)->GetVertex(0)->GetFracture() == false ||
                    //t->GetEdge(i)->GetVertex(1)->GetFracture() == false)) {
                    const Triangle * next = t->GetEdge(i)->GetOtherTriangle(t);
                    if(!next->IsVisited())
                        procList.push((Triangle *)next);
            }
        }
    }
}
Example #13
0
//=============================================================================
// That we're passing in a visitation key is actually a sign that there's
// a more fundamental bug going on.
SurfaceMesh::Vertex* SurfaceMesh::Edge::FindAdjacentVertex( VertexType vertexType, int visitationKey ) const
{
	// Which vertex are we pivoting about?
	Vertex* pivotVertex = 0;
	if( vertexType == CCW_VERTEX )
		pivotVertex = vertex[0];
	else if( vertexType == CW_VERTEX )
		pivotVertex = vertex[1];
	assert->Condition( pivotVertex != 0, "Null pivot vertex!" );

	// Find the last triangle we can find while winding about that vertex
	// in the desired direction.
	bool windingTriangleFound = false;
	Triangle* windingTriangle = triangle;
	do
	{
		if( windingTriangle->visitationKey == visitationKey )
			break;
		windingTriangle->visitationKey = visitationKey;
		int vertexIndex = windingTriangle->FindVertexIndex( pivotVertex );
		int triangleIndex = -1;
		if( vertexType == CCW_VERTEX )
			triangleIndex = ( vertexIndex + 2 ) % 3;
		else if( vertexType == CW_VERTEX )
			triangleIndex = vertexIndex;
		Triangle* adjacentTriangle = windingTriangle->adjacentTriangle[ triangleIndex ];
		if( !adjacentTriangle )
			windingTriangleFound = true;
		else
			windingTriangle = adjacentTriangle;
	}
	while( !windingTriangleFound );
	
	// Return null if the edge doesn't have such a vertex.
	if( !windingTriangleFound )
		return 0;

	// Return the correct vertex of the found triangle.
	int vertexIndex = windingTriangle->FindVertexIndex( pivotVertex );
	if( vertexType == CCW_VERTEX )
		vertexIndex = ( vertexIndex + 2 ) % 3;
	else if( vertexType == CW_VERTEX )
		vertexIndex = ( vertexIndex + 1 ) % 3;
	return windingTriangle->vertex[ vertexIndex ];
}
int main()
{
	//circle tests
	Circle newCircle = Circle(2);
	cout << "newCircle radius is: " << newCircle.getRadius() << endl;
	newCircle.incSides(3);
	cout << "newCircle radius is: " << newCircle.getRadius() << endl;
	std::cin.get();

	//rectangle tests
	Rectangle newRectangle = Rectangle(2, 3);
	cout << "newRectangle side1, side2: " << newRectangle.getSide1() << " , " << newRectangle.getSide2() << endl;
	newRectangle.incSides(3);
	cout << "newRectangle side1, side2: " << newRectangle.getSide1() << " , " << newRectangle.getSide2() << endl;
	std::cin.get();

	//triangle tests
	Triangle newTriangle = Triangle(5, 5, 5);
	cout << "newTriangle side1, side2, side3: " << newTriangle.getSide1() << " , " << newTriangle.getSide2() << " , " << newTriangle.getSide3() << endl;
	cout << "newTriangle's area: " << newTriangle.area() << endl;
	newTriangle.incSides(3);
	cout << "newTriangle side1, side2, side3: " << newTriangle.getSide1() << " , " << newTriangle.getSide2() << " , " << newTriangle.getSide3() << endl;
	std::cin.get();

	return 0;
}
Example #15
0
bool Sweep::Legalize(SweepContext& tcx, Triangle& t)
{
  // To legalize a triangle we start by finding if any of the three edges
  // violate the Delaunay condition
  for (int i = 0; i < 3; i++) {
    if (t.delaunay_edge[i])
      continue;

    Triangle* ot = t.GetNeighbor(i);

    if (ot) {
      Point* p = t.GetPoint(i);
      Point* op = ot->OppositePoint(t, *p);
      int oi = ot->Index(op);

      // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
      // then we should not try to legalize
      if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) {
        t.constrained_edge[i] = ot->constrained_edge[oi];
        continue;
      }

      bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op);

      if (inside) {
        // Lets mark this shared edge as Delaunay
        t.delaunay_edge[i] = true;
        ot->delaunay_edge[oi] = true;

        // Lets rotate shared edge one vertex CW to legalize it
        RotateTrianglePair(t, *p, *ot, *op);

        // We now got one valid Delaunay Edge shared by two triangles
        // This gives us 4 new edges to check for Delaunay

        // Make sure that triangle to node mapping is done only one time for a specific triangle
        bool not_legalized = !Legalize(tcx, t);
        if (not_legalized) {
          tcx.MapTriangleToNodes(t);
        }

        not_legalized = !Legalize(tcx, *ot);
        if (not_legalized)
          tcx.MapTriangleToNodes(*ot);

        // Reset the Delaunay edges, since they only are valid Delaunay edges
        // until we add a new triangle or point.
        // XXX: need to think about this. Can these edges be tried after we
        //      return to previous recursive level?
        t.delaunay_edge[i] = false;
        ot->delaunay_edge[oi] = false;

        // If triangle have been legalized no need to check the other edges since
        // the recursive legalization will handles those so we can end here.
        return true;
      }
    }
  }
  return false;
}
Example #16
0
//=============================================================================
void SurfaceMesh::PathConnectedComponent::CalculateVertexNormals( void )
{
	for( Vertex* vertex = ( Vertex* )vertexList.LeftMost(); vertex; vertex = ( Vertex* )vertex->Right() )
	{
		Zero( vertex->normal );
		double triangleCount = 0.0;
		for( Triangle* triangle = ( Triangle* )triangleList.LeftMost(); triangle; triangle = ( Triangle* )triangle->Right() )
		{
			if( triangle->FindVertexIndex( vertex ) != -1 )
			{
				triangleCount += 1.0;
				Add( vertex->normal, vertex->normal, triangle->normal );
			}
		}
		Scale( vertex->normal, vertex->normal, 1.0 / triangleCount );
		Normalize( vertex->normal, vertex->normal );
	}
}
Example #17
0
std::vector<Triangle> Triangle_Mesh::intersecting_triangles(Triangle with){
	std::vector<Triangle> result;
	for(Triangle t : elements){
		if(with.intersectionWith(t).first){
			result.push_back(t);
		}
	}
	return result;
}
Example #18
0
double distanceLineStringTriangle3D( const LineString& gA, const Triangle& gB )
{
    if ( gA.isEmpty() || gB.isEmpty() ) {
        return std::numeric_limits< double >::infinity() ;
    }

    double dMin = std::numeric_limits< double >::infinity() ;

    const Point& tA = gB.vertex( 0 ) ;
    const Point& tB = gB.vertex( 1 ) ;
    const Point& tC = gB.vertex( 2 ) ;

    for ( size_t i = 0; i < gA.numSegments(); i++ ) {
        dMin = std::min( dMin, distanceSegmentTriangle3D( gA.pointN( i ), gA.pointN( i+1 ), tA, tB, tC ) );
    }

    return dMin ;
}
int
PatchIntegrationRule :: SetUpPointsOnTriangle(int nPoints, MaterialMode mode, GaussPoint ***arry)
{
    numberOfIntegrationPoints = GaussIntegrationRule :: SetUpPointsOnTriangle(nPoints, mode, arry);
    firstLocalStrainIndx = 1;
    lastLocalStrainIndx = 3;
    // convert patch coordinates into element based, update weights accordingly
    for ( int j = 0; j <  numberOfIntegrationPoints; j++ ) {
        GaussPoint *gp = ( * arry ) [ j ];
        patch->convertGPIntoParental(gp); // convert coordinates into parental
        Element *elg = ( Element * ) patch->giveParent();
        double parentArea = elg->computeArea();
        Triangle *tr = ( Triangle * ) patch;
        gp->setWeight(8.0 * gp->giveWeight() * tr->getArea() / parentArea); // update integration weight
    }

    return numberOfIntegrationPoints;
}
void generateTriangle(Vector p0, Vector p1, Vector p2)
{
	Triangle tri = Triangle(p0, p1, p2); 
	positions.push_back(p0);
	positions.push_back(p1);
	positions.push_back(p2);

	normals.push_back(tri.getNormal());
	normals.push_back(tri.getNormal());
	normals.push_back(tri.getNormal());

	indices.push_back(globalIndex);
	globalIndex++;
	indices.push_back(globalIndex);
	globalIndex++;
	indices.push_back(globalIndex);
	globalIndex++;
}
void VertexBasedSegmenter::loadMesh(){

    openMeshFile(this->filename);
    cout<<"Loading "<<this->filename<<endl;
    this->centerMesh = centerCoordinate();

    faceAreas = new float[mesh.getTopSimplexesNum()];
    clusterIndex = new int[mesh.getNumVertex()];
    cout<<"found center"<<endl;

    for(unsigned int ii=0; ii<mesh.getTopSimplexesNum(); ii++){
        Triangle T = mesh.getTopSimplex(ii);
        Normals n = Normals(mesh.getVertex(T.TV(0)), mesh.getVertex(T.TV(1)), mesh.getVertex(T.TV(2)));
        norms.push_back(n);
    }
    cout<<"set normals"<<endl;
    setAreas();
    getBBDiagonal();
    cout<<"Diag "<<this->BBDiagonal<<endl;

    double auxRad = sqrt(mesh.MArea()/(NCluster*M_PI));
    this->maxD = auxRad/BBDiagonal;

    openCurvatureFile(fieldfilename);
    cout<<"Loaded function"<<endl;

    for(int ii=0; ii<mesh.getNumVertex(); ii++)
        clusterIndex[ii]=-1;

    cout<<"Before vertices"<<endl;
    vertexDistances = buildVertexDistances();
    cout<<"Vrtices built"<<endl;
    functionVDistances = buildFunctionVDistances();
    cout<<"function built"<<endl;
    buildGlobalDistances();
    cout<<"global built"<<endl;

    vertexDistances.erase(vertexDistances.begin(), vertexDistances.end());
    functionVDistances.erase(functionVDistances.begin(), functionVDistances.end());

    cout<<"All built, "<<mesh.getNumVertex()<<" vertices and "<<mesh.getTopSimplexesNum()<<" triangles"<<endl;

    //startSeg();
}
Example #22
0
/**
 * Render the list of point
 */
void AlphaView::render (bool flat) 
{
  as.set_alpha(*(iter_alpha));
  //   float normal[3]; 
  //   glGetFloatv(GL_CURRENT_NORMAL, normal);
  for(Finite_facets_iterator iter= as.finite_facets_begin ();
      iter != as.finite_facets_end ();
      iter++) {
    if(as.classify(*iter) == Alpha_shape_3::REGULAR) {
      Triangle t =  as.triangle(*iter);
      Point p0 = t.vertex (0);
      Point p1 = t.vertex (1);
      Point p2 = t.vertex (2);

      if(flat) {
	glColor3f(1,1,1);
	qglviewer::Vec v1(p0[0]-p1[0], p0[1]-p1[1],  p0[2]-p1[2]);
	qglviewer::Vec v2(p1[0]-p2[0], p1[1]-p2[1],  p1[2]-p2[2]);
	qglviewer::Vec v3 = v1^v2;
	v3.normalize();
	glBegin(GL_TRIANGLES);
	  
	glNormal3fv(v3);
	glVertex3f(p0[0], p0[1], p0[2]);
	glVertex3f(p1[0], p1[1], p1[2]);
	glVertex3f(p2[0], p2[1], p2[2]);
	glNormal3fv(-v3);
	glVertex3f(p2[0], p2[1], p2[2]);
	glVertex3f(p1[0], p1[1], p1[2]);
	glVertex3f(p0[0], p0[1], p0[2]);
	glEnd();
      }
      else {
	glColor3f(1,0,0);
	glBegin(GL_LINE_LOOP);	
	glVertex3f(p0[0], p0[1], p0[2]);
	glVertex3f(p1[0], p1[1], p1[2]);
	glVertex3f(p2[0], p2[1], p2[2]);
	glEnd();
      
      }
    }
  }
}
Example #23
0
 bool containsPointInclusive(const Triangle<T>& triangle,
                             const Vector<U, 2>& point, double epsilon)
 {
     auto a = getNormal(triangle.point(1) - triangle.point(0))
              * (point - triangle.point(0));
     if (less<T>(a, 0, epsilon))
         return false;
     auto b = getNormal(triangle.point(2) - triangle.point(1))
              * (point - triangle.point(1));
     if (less<T>(b, 0, epsilon))
         return false;
     auto c = getNormal(triangle.point(0) - triangle.point(2))
              * (point - triangle.point(2));
     return greaterOrEqual<T>(c, 0, epsilon);
 }
Example #24
0
inline Eigen::Matrix<Real,2,1> evaluate_der_point<1>(const Triangle<3>& t, const Point& point, const Eigen::Matrix<Real,3,1>& coefficients)
{
	Eigen::Matrix<Real,2,3> B1;
	B1 << t[1][1] - t[2][1], t[2][1] - t[0][1], t[0][1] - t[1][1],
		t[2][0] - t[1][0], t[0][0] - t[2][0], t[1][0] - t[0][0];
	B1 = B1 / (2 * t.getArea());

	return(B1*coefficients);

}
double	Triangle::rotate_to(const Triangle& other) const {
	double	rot = other.azimut() - azimut();
	while (rot < 0) {
		rot += 2 * M_PI;
	}
	while (rot > 2 * M_PI) {
		rot -= 2 * M_PI;
	}
	return rot;
}
Example #26
0
Edge *Vertex::prevBoundaryEdge() const
{
 Triangle *t;
 Edge *e;
 Vertex *v;

 if (e0 == NULL) return NULL;

 e = e0;
 do
 {
  v = e->oppositeVertex(this);
  t = e->rightTriangle(this);
  if (t == NULL) return e;
  e = t->oppositeEdge(v);
 } while (e != e0);

 return NULL;
}
Example #27
0
/// Performs a raycast considering target ray and the transform of this physics mesh.
List<Intersection> PhysicsMesh::Raycast(Ray & ray, Matrix4f & transform)
{
	List<Intersection> intersections;
	// o-o
	for (int i = 0; i < triangles.Size(); ++i)
	{
		Triangle triangle = *triangles[i];	
		triangle.Transform(transform);
		// Do intersection test
		float distance;
		if (ray.Intersect(triangle, &distance))
		{
			Intersection newI;
			newI.distance = distance;
			intersections.Add(newI);
		}
	}
	return intersections;
}
Example #28
0
bool SaveGridToSTL(Grid& grid, const char* filename,
					ISubsetHandler* pSH,
					AVector3& aPos)
{
	ofstream out(filename);
	if(!out){
		UG_LOG("Couldn't open file " << filename << " for writing\n");
		return false;
	}

	if(!grid.has_vertex_attachment(aPos)){
		UG_LOG("Specified vertex-position attachment missing!\n");
	}

	if(grid.num<Quadrilateral>() > 0){
		UG_LOG("WARNING: The specified grid contains quadrilaterals. "
				"Those won't be written to the stl file!\n");
	}

	Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos);

	const char* solidName = "stlFromUG4";
	out << "solid " << solidName << endl;

	for(Grid::traits<Triangle>::iterator iter = grid.begin<Triangle>();
		iter != grid.end<Triangle>(); ++iter)
	{
		Triangle* f = *iter;
		vector3 n;
		CalculateNormal(n, f, aaPos);
		out << "facet normal " << n.x() << " " << n.y() << " " << n.z() << endl;
		out << "outer loop" << endl;
		for(size_t i = 0; i < 3; ++i){
			vector3 v = aaPos[f->vertex(i)];
			out << "vertex " << v.x() << " " << v.y() << " " << v.z() << endl;
		}
		out << "endloop" << endl;
		out << "endfacet" << endl;
	}

	out << "endsolid " << solidName << endl;
	return true;
}
Example #29
0
void SweepContext::MeshClean(Triangle& triangle)
{
  std::vector<Triangle *> triangles;
  triangles.push_back(&triangle);

  while(!triangles.empty()){
	Triangle *t = triangles.back();
	triangles.pop_back();

    if (t != NULL && !t->IsInterior()) {
      t->IsInterior(true);
      triangles_.push_back(t);
      for (int i = 0; i < 3; i++) {
        if (!t->constrained_edge[i])
          triangles.push_back(t->GetNeighbor(i));
      }
    }
  }
}
Example #30
0
Surfel::Surfel (
    const Material&                 iMaterial,
    const std::vector< Vertex >&    iVertexList,
    const Triangle&                 iTriangle,
    const Vec3Df&                   iTranslation
)   :   m_material ( &iMaterial ),
        m_color ( 0.0f, 0.0f, 0.0f )
{
    const Vertex& iA = iVertexList[iTriangle.getVertex(0)];
    const Vertex& iB = iVertexList[iTriangle.getVertex(1)];
    const Vertex& iC = iVertexList[iTriangle.getVertex(2)];

    BuildFromVertices (
        iA,
        iB,
        iC,
        iTranslation
    );
}