Exemple #1
0
LTriangle2 LMesh::GetTriangle2(uint index)
{
    LTriangle2 f;
    LTriangle t = GetTriangle(index);
    f.vertices[0] = GetVertex(t.a);
    f.vertices[1] = GetVertex(t.b);
    f.vertices[2] = GetVertex(t.c);

    f.vertexNormals[0] = GetNormal(t.a);
    f.vertexNormals[1] = GetNormal(t.b);
    f.vertexNormals[2] = GetNormal(t.c);

    f.textureCoords[0] = GetUV(t.a);
    f.textureCoords[1] = GetUV(t.b);
    f.textureCoords[2] = GetUV(t.c);

    LVector3 a, b;

    a = SubtractVectors(_4to3(f.vertices[1]), _4to3(f.vertices[0]));
    b = SubtractVectors(_4to3(f.vertices[1]), _4to3(f.vertices[2]));

    f.faceNormal = CrossProduct(b, a);

    f.faceNormal = NormalizeVector(f.faceNormal);

    f.materialId = m_tris[index].materialId;

    return f;
}
Exemple #2
0
int Mesh::NewNormal(int a, int b, Scalar c)
{
	Vector &A = GetNormal(a);
	Vector &B = GetNormal(b);

	return AddNormal(A*c + B*(1-c));
}
Exemple #3
0
// Best face normal aligned with N
vec2 OBB::GetSupportNormal(vec2 N) const {
	uint32_t iMin(0);
	float dMin(-FLT_MAX);

	for (uint32_t i = 0; i<4; i++) {
		float d = glm::dot(N, GetNormal(i));
		if (d > dMin) {
			dMin = d;
			iMin = i;
		}
	}

	return GetNormal(iMin);
}
Exemple #4
0
void plInterMeshSmooth::SmoothNormals(hsTArray<plSpanHandle>& sets)
{
    hsTArray<uint16_t>* shareVtx = new hsTArray<uint16_t>[sets.GetCount()];
    hsTArray<uint16_t>* edgeVerts = new hsTArray<uint16_t>[sets.GetCount()];
    FindEdges(sets, edgeVerts);

    int i;
    for( i = 0; i < sets.GetCount()-1; i++ )
    {
        int j;
        for( j = edgeVerts[i].GetCount()-1; j >= 0; --j )
        {
            hsPoint3 pos = GetPosition(sets[i], edgeVerts[i][j]);
            hsVector3 normAccum = GetNormal(sets[i], edgeVerts[i][j]);;

            shareVtx[i].Append(edgeVerts[i][j]);

            int k;
            for( k = i+1; k < sets.GetCount(); k++ )
            {
                FindSharedVerts(pos, sets[k], edgeVerts[k], shareVtx[k], normAccum);
            }

            normAccum.Normalize();
            GetNormal(sets[i], edgeVerts[i][j]) = normAccum;

            for( k = i+1; k < sets.GetCount(); k++ )
            {
                SetNormals(sets[k], shareVtx[k], normAccum);
            }

            // Now remove all the shared verts (which we just processed)
            // from edgeVerts so we don't process them again.
            for( k = i; k < sets.GetCount(); k++ )
            {
                int m;
                for( m = 0; m < shareVtx[k].GetCount(); m++ )
                {
                    int idx = edgeVerts[k].Find(shareVtx[k][m]);
                    hsAssert(idx != edgeVerts[k].kMissingIndex, "Lost vertex between find and remove");
                    edgeVerts[k].Remove(idx);
                }
                shareVtx[k].SetCount(0);
            }
        }
    }

    delete [] shareVtx;
    delete [] edgeVerts;
}
    void Colorize(vtkSmartPointer<vtkPolyData> mesh,
                  std::vector<Camera> dataset) {

        assert(not dataset.empty());
        auto colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
        colors->SetNumberOfComponents(3);
        colors->SetName("Colors");
        auto *const meshNormals = mesh->GetPointData()->GetNormals();
        for (auto idx = 0; idx < mesh->GetNumberOfPoints(); ++idx) {

            // camera image indexes and appropriate dot product
            std::map<std::size_t, double> angles;
            auto normal = GetNormal(meshNormals, idx);
            angles[0] = normal.dot(dataset[0].getDirection());
            for (std::size_t j = 1; j < dataset.size(); ++j) {
                auto angle = normal.dot(dataset[j].getDirection());
                if (angle >= 0.5) {
                    angles[j] = angle;
                }
            }

            Color<double> color = getAverageColor(mesh, dataset, idx, angles);
            colors->InsertNextTuple(reinterpret_cast<double *>(&color));
        }
        mesh->GetPointData()->SetScalars(colors);
    }
void vtkSeismicSliceWidget::SetSlicePosition(double position)
{
    this->vtkImagePlaneWidget::SetSlicePosition(position);

    plane->SetOrigin(GetOrigin());
    plane->SetNormal(GetNormal());
}
void vtkSeismicSliceWidget::SetPlaneOrientationToZAxes()
{
    this->vtkImagePlaneWidget::SetPlaneOrientationToXAxes();

    plane->SetOrigin(GetOrigin());
    plane->SetNormal(GetNormal());
}
Exemple #8
0
const float3& CGround::GetNormalAboveWater(float x, float z, bool synced)
{
	if (GetHeightReal(x, z, synced) <= 0.0f)
		return UpVector;

	return (GetNormal(x, z, synced));
}
Exemple #9
0
int plane_t::BoxOnPlaneSide(box3 box, float epsilon)
{
	vec3	corners[2];
	float	dists[2];
	
	for (int i=0; i < 3; i++)
	{
		vec3 normal = GetNormal();
		
		if (normal[i] < 0)
		{
			corners[0][i] = box.min[i];
			corners[1][i] = box.max[i];
		}
		else
		{
			corners[1][i] = box.min[i];
			corners[0][i] = box.max[i];
		}
	}
	
	dists[0] = Distance(corners[0]);
	dists[1] = Distance(corners[1]);
	
	if(fabsf(dists[0]) < epsilon && fabsf(dists[1]) < epsilon)
		return PLANE_SIDE_ON;
	if(dists[0] >= 0.0f && dists[1] >= 0.0f)
		return PLANE_SIDE_FRONT;
	if(dists[0] <= 0.0f && dists[1] <= 0.0f)
		return PLANE_SIDE_BACK;
	
	return PLANE_SIDE_CROSS;
}
Exemple #10
0
void TPZCartsys::SetAxes(TPZVec<REAL> &x, TPZVec<REAL> &z){
	
	x[0] -= fOrigin[0];
	x[1] -= fOrigin[1];
	x[2] -= fOrigin[2];
	Normalise(x);
	
	fTr(0,0) = x[0];
	fTr(0,1) = x[1];
	fTr(0,2) = x[2];
	
	z[0] -= fOrigin[0];
	z[1] -= fOrigin[1];
	z[2] -= fOrigin[2];
	Normalise(z);
	
	fTr(2,0) = z[0];
	fTr(2,1) = z[1];
	fTr(2,2) = z[2];
	
	TPZVec<REAL> y(3,0.);
	GetNormal(z,x,y);
	fTr(1,0) = y[0];
	fTr(1,1) = y[1];
	fTr(1,2) = y[2];
}
Exemple #11
0
void* InitStructEuclidean() {
	int i,j;
	unsigned long long int temp = 1;
	unsigned long long int M = (temp << 32) - 5;
	confEuclidean *ce = malloc(sizeof(confEuclidean));

	ce->v = malloc((euc->k) * sizeof(double*));
	ce->w = 4;
	ce->t = malloc((euc->k)*sizeof(int));
	for (i = 0; i < euc->k; i++) {

		ce->t[i] = (int)GetUniform(0, ce->w);
		ce->v[i] = malloc((euc->dim) * sizeof(double));
		for (j = 0; j < euc->dim; j++) {
			ce->v[i][j] = GetNormal(0, 1);
		}
	}

	ce->gt = malloc((euc->k) * sizeof(unsigned int));
	for (i = 0; i < euc->k; i++) {
		//ce->gt[i] = malloc((euc->dim) * sizeof(double));
		//for (j = 0; j < euc->dim; j++) {
		ce->gt[i] = (unsigned int)GetUniform(0, M);
		//printf("%u\n", ce->gt[i]);
		//printf("%f\n",ce->gt[i][j]);
		//}
	}


	return ce;
}
Luxko::Plane3DH Luxko::Triangle3DH::GetPlane() const
{
	auto normal = GetNormal();
	Plane3DH result;
	result.InitializeN(_P0, normal);
	return result;
}
Exemple #13
0
    PANEL(Vect3 P1, Vect3 P2, Vect3 P3, Vect3 P4) {
        C1 = P1;
        C2 = P2;
        C3 = P3;
        C4 = P4;
        C1o = C1;
        C2o = C2;
        C3o = C3;
        C4o = C4;
        edgeX1 = edgeX2 = dF = Vect3(0.0);
        Sigma = Mu = PhiWakePrev = 0.0;
        Gamma = Phi = Sigma = Mu = 0.0;
        Area = MaxDiagonal = Gamma = Vn = MuPrev = GammaPrev = 0.0;
        Centroid = Vect3(.25 * (C1 + C2 + C3 + C4));
        Owner = NULL;
        OtherBoundarySurface = AttachedProtoWake = SheddingSurface = NULL;
        Neighb = NULL;
        Theta = 0.0;
        isBound = isTop = isWake = false;
        BoundBC = ID = -1;
        TRANS.assign(3, Vect3(0.));

        PhiPrev = Array <REAL> (4, 0.0);
        Cloc = Rloc = 0.0;
        Vfmm = dVFMM_dt = VWakePrev = Vect3(0.);
        DoubletValidRange2 = ValidRange = 1e32;
        GetNormal();
    }
Exemple #14
0
 bool Ellipse::InEllipse(const NX::vector<float, 3> &point) const{
     const NX::vector<float, 3> v = point - GetCenter();
     const float lx = NX::Dot(v, GetLongAxis());
     const float ly = NX::Dot(v, GetShortAxis());
     const float dx = lx / GetLongAxisLength();
     const float dy = ly / GetShortAxisLength();
     return NX::EqualZero(NX::Dot(v, GetNormal())) && dx * dx + dy * dy <= kf1;
 }
 void PlaneGeometry::PrintSelf( std::ostream& os, itk::Indent indent ) const
 {
   Superclass::PrintSelf(os,indent);
   os << indent << " ScaleFactorMMPerUnitX: "
     << GetExtentInMM(0) / GetExtent(0) << std::endl;
   os << indent << " ScaleFactorMMPerUnitY: "
     << GetExtentInMM(1) / GetExtent(1) << std::endl;
   os << indent << " Normal: " << GetNormal() << std::endl;
 }
Exemple #16
0
//---------------------------------------------------------------------------
//  GetQuadNormal()
//     Get a normal vector for a face constituted by four points.
//     4点からなる面の法線を得る
//---------------------------------------------------------------------------
MQPoint GetQuadNormal(const MQPoint& p0, const MQPoint& p1, const MQPoint& p2, const MQPoint& p3)
{
	MQPoint n,n1a,n1b,n2a,n2b;

	n1a = GetNormal(p0, p1, p2);
	n1b = GetNormal(p0, p2, p3);
	n2a = GetNormal(p1, p2, p3);
	n2b = GetNormal(p1, p3, p0);

	// 凹型や歪んだ四角形の場合は片方の内積が小さくなるので、
	// 2法線の内積の値を比較して、大きい方を選ぶ
	if(GetInnerProduct(n1a,n1b) > GetInnerProduct(n2a,n2b)) {
		n = Normalize(n1a + n1b);
	} else {
		n = Normalize(n2a + n2b);
	}

	return n;
}
// Init the ditc of (*Triangles) and the dict of (*ControlP)
void GenerateLOD::Init_Triangles_And_ControlP_EdgeCollapse(FbxMesh *pMesh, FbxVector4 *pControlPoints)
{
	int triangleCounts = pMesh->GetPolygonCount();
	int ElementUVCount = pMesh->GetElementUVCount();
	if (ElementUVCount < 1) {
		MessageBox(NULL, "Do not read the related uv information", "message", 0);
	}
	for (int i = 0; i < triangleCounts; ++i) {
		int cp0 = pMesh->GetPolygonVertex(i, 0);
		int cp1 = pMesh->GetPolygonVertex(i, 1);
		int cp2 = pMesh->GetPolygonVertex(i, 2);

		//(*Triangles)[i] = Face(); //Init a Polygon for i'th triangle
		(*Triangles)[i].points = { cp0, cp1, cp2 };
		//std::vector<FbxDouble> n = GetNormal(pControlPoints, cp0, cp1, cp2);
		(*Triangles)[i].normal = GetNormal(pControlPoints, cp0, cp1, cp2);

		// Set the three vertex's uv coordinate
		int uvindex0 = pMesh->GetTextureUVIndex(i, 0);
		int uvindex1 = pMesh->GetTextureUVIndex(i, 1);
		int uvindex2 = pMesh->GetTextureUVIndex(i, 2);

		(*Triangles)[i].uvs = { uvindex0, uvindex1, uvindex2 };

		// for Controlp[cp0]
		//if ((*ControlP).find(cp0) == (*ControlP).end())
		//(*ControlP)[cp0] = Point();
		Point &P0 = (*ControlP)[cp0];
		// uv, Ti, Vi for (*ControlP)[cp0]
		P0.uvSet.insert(uvindex0);
		P0.Ti.insert(i);
		P0.Vi.insert(cp1);
		P0.Vi.insert(cp2);

		// for Controlp[cp1]
		//if ((*ControlP).find(cp1) == (*ControlP).end())
		//(*ControlP)[cp1] = Point();
		Point &P1 = (*ControlP)[cp1];
		// uv, Ti, Vi for (*ControlP)[cp0]
		P1.uvSet.insert(uvindex1);
		P1.Ti.insert(i);
		P1.Vi.insert(cp0);
		P1.Vi.insert(cp2);

		// for Controlp[cp2]
		//if ((*ControlP).find(cp2) == (*ControlP).end())
		//(*ControlP)[cp2] = Point();
		Point &P2 = (*ControlP)[cp2];
		// uv, Ti, Vi for (*ControlP)[cp0]
		P2.uvSet.insert(uvindex2);
		P2.Ti.insert(i);
		P2.Vi.insert(cp0);
		P2.Vi.insert(cp1);
	}
}
Exemple #18
0
void Wave::UpdateMesh()
{
	for (UINT i = 0; i < m_M; ++i)
	{
		for (UINT j = 0; j < m_N; ++j)
		{
			m_Data->m_Positions[i * m_M + j].y = GetHeight(i, j, m_M, m_N, m_Time);
			m_Data->m_Normals[i * m_M + j] = GetNormal(i, j, m_M, m_N, m_Time);
		}
	}
}
void VolumeSplatter::SampleVoxel(const int x, const int y, const int z) {
	GLubyte data = SampleVolume(x, y, z);
	if(data>isoValue) {
		Vertex v; 
		v.pos.x = (float)x;
		v.pos.y = (float)y;
		v.pos.z = (float)z;			 			
		v.normal = GetNormal(x, y, z);
		v.pos *= invDim; 
		vertices.push_back(v);
	} 
}
Exemple #20
0
bool
vsMeshMakerTriangleVertex::AttemptMergeWith( vsMeshMakerTriangleVertex *other, const vsVector3D &faceNormalOther )
{
	const float epsilon = 0.01f;
	const float sqEpsilon = epsilon*epsilon;

	bool closeEnough = ((other->m_position - m_position).SqLength() < sqEpsilon);
	bool colorMatches = (other->m_color == m_color);
	bool texelMatches = ((other->m_texel - m_texel).SqLength() < sqEpsilon);

	//vsVector2D deltaTexel = other->m_texel - m_texel;
	//deltaTexel.x -= vsFloor(deltaTexel.x+0.5f);
	//deltaTexel.y -= vsFloor(deltaTexel.y+0.5f);

	if ( closeEnough && colorMatches ) //&& deltaTexel.SqLength() < sqEpsilon )
	{
		// check my normal against 'faceNormalOther'
		//vsAssert( m_flags & Flag_Normal, "error:  merging when I have no normal set??" );
		vsAssert( GetFirstTriangle(), "Merging a vertex which doesn't have any triangles??" );

		//if ( m_normal.Dot( faceNormalOther ) > s_mergeTolerance )
		vsVector3D faceNormal = GetFirstTriangle()->m_faceNormal;
		if ( faceNormal.Dot( faceNormalOther ) > s_mergeTolerance )
		{
			if ( m_mergeCount == 0 )
			{
				m_totalNormal = GetNormal();	// we keep track of the running total, so we can blend correctly.
			}

			m_mergeCount++;
			m_totalNormal += faceNormalOther;
			vsVector3D newNormal = m_totalNormal;
			newNormal.Normalise();
			SetNormal( newNormal );

			if ( !texelMatches )
			{
				other->SetNormal( newNormal );	// set the normal explicitly,
												// just to force the 'has normal'
												// flag on.

				// make the other vertex fake match me.
				other->m_fakeNormalMergedWith = this;
			}

			return texelMatches;
		}
	}

	vsAssert(false,"Tried to merge things taht can't merge??");
	return false;
}
Exemple #21
0
 PANEL(PANEL &C)  {
     C1 =  C.C1; C2 =  C.C2; C3 =  C.C3; C4 =  C.C4;
     C1o = C.C1; C2o = C.C2; C3o = C.C3; C4o = C.C4;
     Sigma = C.Sigma;
     Mu = C.Mu;
     Gamma = C.Gamma;
     Phi = C.Phi;
     Area = C.Area;
     MaxDiagonal = C.MaxDiagonal;
     Gamma = C.Gamma;
     GammaPrev = C.GammaPrev;
     Vn = C.Vn;
     MuPrev = C.MuPrev;
     Centroid = C.Centroid;
     TRANS.allocate(3);
     TRANS[0] = C.TRANS[0];
     TRANS[1] = C.TRANS[1];
     TRANS[2] = C.TRANS[2];
     Owner = C.Owner;
     isBound = C.isBound;
     BoundBC = C.BoundBC;
     isTop  = C.isTop;
     Neighb = C.Neighb;
     Theta = C.Theta;
     OtherBoundarySurface = C.OtherBoundarySurface;
     AttachedProtoWake = C.AttachedProtoWake;
     edgeX1 = C.edgeX1;
     edgeX2 = C.edgeX2;
     SheddingSurface = C.SheddingSurface;
     Xcb = C.Xcb;
     Group = C.Group;
     isWake = C.isWake;
     GetNormal();
     PhiPrev = C.PhiPrev;
     VWake = C.VWake;
     Cloc = C.Cloc;
     Rloc = C.Rloc;
     dF = C.dF;
     ID = C.ID;
     Vfmm = C.Vfmm;
     dVFMM_dt = C.dVFMM_dt;
     NC1 = C.NC1;
     NC2 = C.NC2; 
     NC3 = C.NC3; 
     NC4 = C.NC4;
     DoubletValidRange2 = C.DoubletValidRange2;
     ValidRange = C.ValidRange;
     PhiWakePrev = C.PhiWakePrev;
     VWakePrev = C.VWakePrev;
     
 }
Exemple #22
0
    //-----------------------------------------------------------------------------------
    static void ImportVertex(MeshBuilder& builder, const Matrix4x4& transform, FbxMesh* mesh, int polyIndex, int vertIndex, std::vector<SkinWeight>& skinWeights)
    {
        Vector3 normal;
        if (GetNormal(normal, transform, mesh, polyIndex, vertIndex))
        {
            builder.SetNormal(normal);

            //Temporary hack to get around not supporting multiple vertex definitions
            Vector3 bitangent = Vector3::UP;
            if (normal == bitangent)
            {
                bitangent = Vector3::FORWARD;
            }
            Vector3 tangent = Vector3::Cross(bitangent, normal);
            bitangent = Vector3::Cross(normal, tangent);

            builder.SetTangent(tangent);
            builder.SetBitangent(bitangent);
        }
        
        RGBA color;
        if (GetColor(color, mesh, polyIndex, vertIndex))
        {
            builder.SetColor(color);
        }

        Vector2 uv;
        if (GetUV(uv, mesh, polyIndex, vertIndex, 0))
        {
            builder.SetUV(uv);
        }

        //Set Skin Weights
        int controlIndex = mesh->GetPolygonVertex(polyIndex, vertIndex);
        if (controlIndex < skinWeights.size())
        {
            builder.SetBoneWeights(skinWeights[controlIndex].indices, skinWeights[controlIndex].weights);
            builder.RenormalizeSkinWeights(); //Just to be safe.
        }
        else
        {
            builder.ClearBoneWeights();
        }

        Vector3 position;
        if (GetPosition(&position, transform, mesh, polyIndex, vertIndex))
        {
            builder.AddVertex(position);
        }
    }
Exemple #23
0
void csTerrainCell::RecalculateNormalData ()
{
  csLockedNormalData cellNData = GetNormalData ();

  for (int y = 0; y < gridWidth; ++y)
  {
    csVector3* nRow = cellNData.data + y * gridHeight;

    for (int x = 0; x < gridHeight; ++x)
    {
      *nRow++ = GetNormal (x, y);
    }
  }
  needTangentsUpdate = true;
}
Exemple #24
0
void* InitStructCosine() {
	int i;
	confCosine *ce = malloc(sizeof(confCosine));

	ce->r = malloc(( co.k) * sizeof(double*));
	int j;
	for (j = 0; j < co.k; ++j) {
		ce->r[j] = malloc((co.dim) *sizeof(double));
	}
	for (j = 0; j < co.k; ++j) {
		for (i = 0; i <  co.dim; i++) {
			ce->r[j][i] = GetNormal(0, 1);
		}
	}
	return ce;
}
Exemple #25
0
 bool Cone::InCone(const NX::vector<float, 3> &point) const{
     const NX::vector<float, 3> v = point - GetCenter();
     const float lx = NX::Dot(v, GetLongAxis());
     const float ly = NX::Dot(v, GetNormal());
     const float lz = NX::Dot(v, GetShortAxis());
     if(ly < kf0 || ly > GetHeight()){
         return false;
     }
     
     const float t  = kf1 - ly / GetHeight();
     const float rx = GetLongAxisLength()  * t;
     const float rz = GetShortAxisLength() * t;
     const float dx = lx / rx;
     const float dz = lz / rz;
     return dx * dx + dz * dz <= kf1;
 }
Exemple #26
0
void plInterMeshSmooth::FindSharedVerts(hsPoint3& searchPos, plSpanHandle& set, hsTArray<uint16_t>& edgeVerts, hsTArray<uint16_t>& shareVtx, hsVector3& normAccum)
{
    int i;
    for( i = 0; i < edgeVerts.GetCount(); i++ )
    {
        hsPoint3 pos = GetPosition(set, edgeVerts[i]);
        hsVector3 norm = GetNormal(set, edgeVerts[i]);
        if( searchPos == pos )
        {
            if( norm.InnerProduct(normAccum) > fMinNormDot )
            {
                shareVtx.Append(edgeVerts[i]);
                normAccum += norm;
            }
        }
    }
}
Exemple #27
0
void TaperedCylinder(float h, float r1, float r2, int nslices)
{
	int n;
	float dth = (2 * PI) / nslices;

	for (n = 0; n != nslices; n++)
	{
		glBegin(GL_POLYGON);
			GetNormal((r2 * cos((n + 1) * dth)) - (r1 * cos(n * dth)), h, (r2 * sin((n + 1) * dth)) - (r1 * sin(n * dth)),
					 (r1 * cos((n + 1) * dth)) - (r1 * cos(n * dth)), 0, (r1 * sin((n + 1) * dth)) - (r1 * sin(n * dth)));
			glNormal3f(normal_vector[0], normal_vector[1], normal_vector[2]);
			glVertex3f(r1 * cos(n * dth), 0, r1 * sin(n * dth));
			glVertex3f(r1 * cos((n + 1) * dth), 0, r1 * sin((n + 1) * dth));
			glVertex3f(r2 * cos((n + 1) * dth), h, r2 * sin((n + 1) * dth));
			glVertex3f(r2 * cos(n * dth), h, r2 * sin(n * dth));
		glEnd();
	}  // for loop
}  // TaperedCylinder
void CConvexHull::EndSetFromPoints(SFloat3* psNormals, int iStride, CConvexHullGenerator* psConvexHullGenerator)
{
	SFreeListIterator		sIter;
	int						i;
	SFloat3*				psNormal;

	if (psNormals)
	{
		i = 0;
		psNormal = (SFloat3*)psConvexHullGenerator->GetNormals()->StartIteration(&sIter);
		while (psNormal)
		{
			*GetNormal(psNormals, iStride, i) = *psNormal;

			i++;
			psNormal = (SFloat3*)psConvexHullGenerator->GetNormals()->Iterate(&sIter);
		}
	}

	psConvexHullGenerator->Kill();
}
Exemple #29
0
  /// Approximates the surface points and normals.
  /// \details Returns resulting position and if a pointer is passed to
  /// the third argument also normals.
  /// Watch out! The function calls clear on the normal container!
  /// \param[in]  n       Number of points in the first direction.
  /// \param[in]  m       Number of points in the second direction.
  /// \param[out] normal  Pointer to a container
  ///  for storage of surface normals.(optional)
  /// \return Returns the surface positions.
  std::vector<glm::vec3> ConstructApproximation(
      uint n,
      uint m,
      std::vector<glm::vec3> * normal = nullptr) {
    float inv_n = 1 / static_cast<float>(n),
      inv_m = 1 / static_cast<float>(m);
    std::vector<glm::vec3> position;
    if (normal) {
      normal->clear();
      for (uint i=0;i < n;++i)
	for (uint j=0;j < m;++j) {
	  position.push_back(GetPoint(i * inv_n,j * inv_m));
	  normal->push_back(GetNormal(i * inv_n,j * inv_m));
	}
    } else {
      for (uint i=0;i < n;++i)
	for (uint j=0;j < m;++j)
	  position.push_back(GetPoint(i * inv_n,j * inv_m));
    }
    return position;
  }
bool Luxko::Triangle3DH::IntersectBarycentric(const Line3DH& line, Vector3f& barycentricCoordinates) const
{
	auto normal = GetNormal();
	Plane3DH plane;
	plane.InitializeN(_P0, normal);

	if (line.Perpendicular(normal)) {
		// CAUTION: containing is out.
		return false;
	}
	else {
		auto point = line.Intersect(plane);
		auto R = point - _P0;
		auto Q1 = _P1 - _P0;
		auto Q2 = _P2 - _P0;

		auto Q1Sq = Q1*Q1;
		auto Q2Sq = Q2*Q2;
		auto Q1dotQ2 = Q1*Q2;
		auto Det = Q1Sq*Q2Sq - Q1dotQ2*Q1dotQ2;

		auto RdotQ1 = R*Q1;
		auto RdotQ2 = R*Q2;

		auto w1 = (Q2Sq*RdotQ1 - Q1dotQ2*RdotQ2) / Det;

		auto w2 = (Q1Sq*RdotQ2 - Q1dotQ2*RdotQ1) / Det;
		auto w0 = 1.f - w1 - w2;
		if (w1 < 0.f || w2 < 0.f || w0 < 0.f) {
			return false;
		}
		else {
			barycentricCoordinates._x = w0;
			barycentricCoordinates._y = w1;
			barycentricCoordinates._z = w2;
			return true;
		}
	}

}