Beispiel #1
0
const Triangle& FullEdge::GetOtherTriangle(const Triangle &TCompare) const
{
    if(GetTriangle(0) == TCompare)
    {
        return GetTriangle(1);
    }
    if(GetTriangle(1) == TCompare)
    {
        return GetTriangle(0);
    }
    SignalError("FullEdge::GetOtherTriangle failed");
    return Triangle::Invalid;
}
Beispiel #2
0
Vec3f FullEdge::ComputeLoopSubdivisionPos()
{
    if(Boundary())
    {
        return 0.5f * (GetVertex(0).Pos() + GetVertex(1).Pos());
    }
    else
    {
        Vertex &VOpposite0 = GetTriangle(0).GetOtherVertex(*this);
        Vertex &VOpposite1 = GetTriangle(1).GetOtherVertex(*this);

        return   (1.0f / 8.0f) * (VOpposite0.Pos() + VOpposite1.Pos())
               + (3.0f / 8.0f) * (GetVertex(0).Pos() + GetVertex(1).Pos());
    }
}
Beispiel #3
0
    double Mesh::ComputeVolume() const
    {
        const size_t nV = GetNPoints();
        const size_t nT = GetNTriangles();
        if (nV == 0 || nT == 0)
        {
            return 0.0;
        }

        Vec3<double> bary(0.0, 0.0, 0.0);
        for (size_t v = 0; v < nV; v++)
        {
            bary +=  GetPoint(v);
        }
        bary /= static_cast<double>(nV);

        Vec3<double> ver0, ver1, ver2;
        double totalVolume = 0.0;
        for(size_t t = 0; t < nT; t++)
        {
            const Vec3<int> & tri = GetTriangle(t);
            ver0 = GetPoint(tri[0]);
            ver1 = GetPoint(tri[1]);
            ver2 = GetPoint(tri[2]);
            totalVolume += ComputeVolume4(ver0, ver1, ver2, bary);
        }
        return totalVolume/6.0;
    }
void Convert_shape_line_polygon_to_triangles( SHAPE_POLY_SET &aPolyList,
                                              CGENERICCONTAINER2D &aDstContainer,
                                              float aBiuTo3DunitsScale ,
                                              const BOARD_ITEM &aBoardItem )
{

    aPolyList.CacheTriangulation();
    const double conver_d = (double)aBiuTo3DunitsScale;

    for( unsigned int j = 0; j < aPolyList.TriangulatedPolyCount(); j++ )
    {
        auto triPoly = aPolyList.TriangulatedPolygon( j );

        for( size_t i = 0; i < triPoly->GetTriangleCount(); i++ )
        {
            VECTOR2I a;
            VECTOR2I b;
            VECTOR2I c;
            triPoly->GetTriangle( i, a, b, c );

            aDstContainer.Add( new CTRIANGLE2D( SFVEC2F( a.x * conver_d,
                                                        -a.y * conver_d ),
                                                SFVEC2F( b.x * conver_d,
                                                        -b.y * conver_d ),
                                                SFVEC2F( c.x * conver_d,
                                                        -c.y * conver_d ),
                                                aBoardItem ) );
        }

    }
}
Beispiel #5
0
void SubMesh::DrawImmediate()
{
	if (!loaded)
		return;
	glBegin(GL_TRIANGLES);
	for (int i = 0; i < meshInfo.triCount; ++i)
	{
		Triangle t = GetTriangle(i);
		if (HasTextureCoords())
		{
			for (int j = 0; j < 3; ++j)
			{
				VertexPositionTexcoord* vpt = GetVertexData<VertexPositionTexcoord>(t.index[j]);
				glVertex3fv(vpt->position);
				glTexCoord2fv(vpt->texCoord);
			}
		}
		else
		{	
			for (int j = 0; j < 3; ++j)
			{
				VertexPositionNormalTexcoord* vpnt = GetVertexData<VertexPositionNormalTexcoord>(t.index[j]);
				glVertex3fv(vpnt->position);
				if (HasNormals())
					glNormal3fv(vpnt->normal);
				if (HasTextureCoords())
					glTexCoord2fv(vpnt->texCoord);
			}
		}
	}
	glEnd();
}
   int DelaunayTriangle::NeighbourReference(int t)
   {
      DelaunayTriangle* pNeighbourTriangle = GetTriangle(t);
      if (pNeighbourTriangle == 0)
      {
         return -1;
      }

      if (pNeighbourTriangle->GetTriangle(0) == this)
      {
         return 0;
      }
      else if (pNeighbourTriangle->GetTriangle(1) == this)
      {
         return 1;
      }
      else if (pNeighbourTriangle->GetTriangle(2) == this)
      {
         return 2;
      }
      else
      {
         assert(false);
         return -1;
      }
   }
Beispiel #7
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;
}
void STLTopology :: SaveBinary (const char* filename, const char* aname) const
{
  ofstream ost(filename);
  PrintFnStart("Write STL binary file '",filename,"'");

  if (sizeof(int) != 4 || sizeof(float) != 4) 
    {PrintWarning("for stl-binary compatibility only use 32 bit compilation!!!");}

  //specific settings for stl-binary format
  const int namelen = 80; //length of name of header in file
  const int nospaces = 2; //number of spaces after a triangle

  //write header: aname
  int i, j;
  char buf[namelen+1];
  int strend = 0;
  for(i = 0; i <= namelen; i++) 
    {
      if (aname[i] == 0) {strend = 1;}
      if (!strend) {buf[i] = aname[i];}
      else {buf[i] = 0;}
    }

  FIOWriteString(ost,buf,namelen);
  PrintMessage(5,"header = ",buf);

  //RWrite Number of facets
  int nofacets = GetNT();
  FIOWriteInt(ost,nofacets);
  PrintMessage(5,"NO facets = ", nofacets);

  float f;
  char spaces[nospaces+1];
  for (i = 0; i < nospaces; i++) {spaces[i] = ' ';}
  spaces[nospaces] = 0;

  for (i = 1; i <= GetNT(); i++)
    {
      const STLTriangle & t = GetTriangle(i);

      const Vec<3> & n = t.Normal();
      f = n(0); FIOWriteFloat(ost,f);
      f = n(1); FIOWriteFloat(ost,f);
      f = n(2); FIOWriteFloat(ost,f);

      for (j = 1; j <= 3; j++)
	{
	  const Point3d p = GetPoint(t.PNum(j));
	  
	  f = p.X(); FIOWriteFloat(ost,f);
	  f = p.Y(); FIOWriteFloat(ost,f);
	  f = p.Z(); FIOWriteFloat(ost,f);
	}
      FIOWriteString(ost,spaces,nospaces);
    }
  PrintMessage(5,"done");
}
Beispiel #9
0
int TriMesh::ClosestPoint(const Vector3& pt,Vector3& cp) const
{
  int tmin=-1;
  Real dmin=Inf;
  Vector3 temp;
  Triangle3D tri;
  for(size_t i=0;i<tris.size();i++) {
    GetTriangle(i,tri);
    temp = tri.closestPoint(pt);
    Real d2=temp.distanceSquared(pt);
    if(d2 < dmin) {
      tmin = (int)i;
      dmin = d2;
      cp = temp;
    }
  }
  return tmin;
}
Beispiel #10
0
int TriMesh::RayCast(const Ray3D& r,Vector3& pt) const
{
  int tmin=-1;
  Real dmin=Inf;
  Real d;
  Vector2 uv;
  Triangle3D tri;
  for(size_t i=0;i<tris.size();i++) {
    GetTriangle(i,tri);
    if(tri.rayIntersects(r,&d,&uv.x,&uv.y)) {
      if(d < dmin) {
	tmin = (int)i;
	dmin = d;
	pt = tri.planeCoordsToPoint(uv);
      }
    }
  }
  return tmin;
}
Beispiel #11
0
	bool MeshDecimator::ManifoldConstraint(long v1, long v2) const
	{
		std::set<long> vertices;
		long a, b;
        long idEdge1;
        long idEdge2;
		long idEdgeV1V2 = 0;
		for(size_t itE1 = 0; itE1 < m_vertices[v1].m_edges.Size(); ++itE1)
		{
            idEdge1 = m_vertices[v1].m_edges[itE1];
			a = (m_edges[idEdge1].m_v1 == v1) ? m_edges[idEdge1].m_v2 : m_edges[idEdge1].m_v1;
			vertices.insert(a);
			if (a != v2)
			{
				for(size_t itE2 = 0; itE2 < m_vertices[v2].m_edges.Size(); ++itE2)
				{
                    idEdge2 = m_vertices[v2].m_edges[itE2];
					b = (m_edges[idEdge2].m_v1 == v2) ? m_edges[idEdge2].m_v2 : m_edges[idEdge2].m_v1;
					vertices.insert(b);
					if ( a==b )
					{
						if (GetTriangle(v1, v2, a) == -1)
						{
							return false;
						}
					}
				}
			}
			else
			{
				idEdgeV1V2 = idEdge1;
			}
		}
		if (vertices.size() <= 4 || ( m_vertices[v1].m_onBoundary && m_vertices[v2].m_onBoundary && !m_edges[idEdgeV1V2].m_onBoundary))
		{
			return false;
		}
		return true;
	}
void STLTopology :: SaveSTLE (const char* filename) const
{
  ofstream outf (filename);
  int i, j;
  
  outf << GetNT() << endl;
  for (i = 1; i <= GetNT(); i++)
    {
      const STLTriangle & t = GetTriangle(i);
      for (j = 1; j <= 3; j++)
	{
	  const Point3d p = GetPoint(t.PNum(j));
	  outf << p.X() << " " << p.Y() << " " << p.Z() << endl;
	}
    }


  int ned = 0;
  for (i = 1; i <= GetNTE(); i++)
    {
      if (GetTopEdge (i).GetStatus() == ED_CONFIRMED)
	ned++;
    }
  
  outf << ned << endl;

  for (i = 1; i <= GetNTE(); i++)
    {
      const STLTopEdge & edge = GetTopEdge (i);
      if (edge.GetStatus() == ED_CONFIRMED)
	for (j = 1; j <= 2; j++)
	  {
	    const Point3d p = GetPoint(edge.PNum(j));
	    outf << p.X() << " " << p.Y() << " " << p.Z() << endl;
	  }
    }      
}
Beispiel #13
0
 bool Mesh::IsInside(const Vec3<double> & pt) const
 {
     const size_t nV = GetNPoints();
     const size_t nT = GetNTriangles();
     if (nV == 0 || nT == 0)
     {
         return false;
     }
     Vec3<double> ver0, ver1, ver2;
     double volume;
     for (size_t t = 0; t < nT; t++)
     {
         const Vec3<int> & tri = GetTriangle(t);
         ver0 = GetPoint(tri[0]);
         ver1 = GetPoint(tri[1]);
         ver2 = GetPoint(tri[2]);
         volume = ComputeVolume4(ver0, ver1, ver2, pt);
         if (volume < 0.0)
         {
             return false;
         }
     }
     return true;
 }
Beispiel #14
0
Plane Mesh::GetPlane(int index)
{
	Triangle T;
	T = GetTriangle(index);
	return Plane(T.normal, T.vertexes[0]);
}
Beispiel #15
0
bool FullEdge::Boundary() const
{
    return (GetTriangle(1) == Triangle::Boundary);
}
Beispiel #16
0
	void MeshDecimator::EdgeCollapse(long v1, long v2)
	{
		long u, w;
		int shift;
		long idTriangle;
		for(size_t itT = 0; itT < m_vertices[v2].m_triangles.Size(); ++itT)
		{
            idTriangle =  m_vertices[v2].m_triangles[itT];
			if (m_triangles[idTriangle].X() == v2)
			{
				shift = 0;
				u = m_triangles[idTriangle].Y();
				w = m_triangles[idTriangle].Z();
			}
			else if (m_triangles[idTriangle].Y() == v2)
			{
				shift = 1;
				u = m_triangles[idTriangle].X();
				w = m_triangles[idTriangle].Z();
			}
			else
			{
				shift = 2;
				u = m_triangles[idTriangle].X();
				w = m_triangles[idTriangle].Y();
			}

			if ((u == v1) || (w == v1))
			{
				m_trianglesTags[idTriangle] = false;
				m_vertices[u].m_triangles.Erase(idTriangle);						
				m_vertices[w].m_triangles.Erase(idTriangle);
				m_nTriangles--;
			}
			else if (GetTriangle(v1, u, w) == -1)
			{
				m_vertices[v1].m_triangles.Insert(idTriangle);
				m_triangles[idTriangle][shift] = v1;
			}
			else
			{
				m_trianglesTags[idTriangle] = false;
				m_vertices[u].m_triangles.Erase(idTriangle);						
				m_vertices[w].m_triangles.Erase(idTriangle);
				m_nTriangles--;
			}
		}
        long idEdge = 0;
		for(size_t itE = 0; itE < m_vertices[v2].m_edges.Size(); ++itE)
		{
            idEdge = m_vertices[v2].m_edges[itE];
			w = (m_edges[idEdge].m_v1 == v2)? m_edges[idEdge].m_v2 : m_edges[idEdge].m_v1;
			if (w==v1)
			{
				m_edges[idEdge].m_tag = false;
				m_vertices[w].m_edges.Erase(idEdge);
				m_nEdges--;
			}
			else if ( GetEdge(v1, w) == -1)
			{
				if (m_edges[idEdge].m_v1 == v2)	m_edges[idEdge].m_v1 = v1;
				else							m_edges[idEdge].m_v2 = v1;
				m_vertices[v1].m_edges.Insert(idEdge);			
			}
			else
			{
				m_edges[idEdge].m_tag = false;
				m_vertices[w].m_edges.Erase(idEdge);
				m_nEdges--;
			}
		}
		m_vertices[v2].m_tag = false;
		m_nVertices--;
		// update boundary edges
		SArray<long, 64> incidentVertices;
		incidentVertices.PushBack(v1);
		for(size_t itE = 0; itE < m_vertices[v1].m_edges.Size(); ++itE)
		{
			incidentVertices.PushBack((m_edges[idEdge].m_v1!= v1)?m_edges[idEdge].m_v1:m_edges[idEdge].m_v2);
            idEdge = m_vertices[v1].m_edges[itE];
			m_edges[idEdge].m_onBoundary = (IsBoundaryEdge(m_edges[idEdge].m_v1, m_edges[idEdge].m_v2) != -1);
		}		
		// update boundary vertices
		long idVertex;
		for(size_t itV = 0; itV < incidentVertices.Size(); ++itV)
		{
			idVertex = incidentVertices[itV];
			m_vertices[idVertex].m_onBoundary = false;
			for(size_t itE = 0; itE < m_vertices[idVertex].m_edges.Size(); ++itE)
			{
				idEdge = m_vertices[idVertex].m_edges[itE];
				if (m_edges[idEdge].m_onBoundary)
				{
					m_vertices[idVertex].m_onBoundary = true;
					break;
				}
			}
		}		
	}
Beispiel #17
0
Void TriangleMesh::_ComputeDerivateNormals( Matrix4 * outDerivateNormals, UInt iVertexCount, UInt iTriangleCount,
                                            const Byte * arrPositions, const Byte * arrNormals, UInt iVertexSize ) const
{
    // Create temp storage
    Matrix4 * arrProjTangents = New Matrix4[iVertexCount];
    Matrix4 * arrDeltaTangents = New Matrix4[iVertexCount];
    MemZero( arrProjTangents, iVertexCount * sizeof(Matrix4) );
    MemZero( arrDeltaTangents, iVertexCount * sizeof(Matrix4) );

    // Compute projected & delta tangents
    UInt i, iRow, iCol;
    UInt iTriangle[3];
    UInt iA, iB, iC;
    const Vertex4 *pA, *pB, *pC;
    const Vector4 *pNormA, *pNormB, *pNormC;

    Vector3 vEdge, vProj, vDelta;
    Matrix4 matInverse;

    for( i = 0; i < iTriangleCount; ++i ) {
        GetTriangle( i, iTriangle[0], iTriangle[1], iTriangle[2] );
        iTriangle[0] *= iVertexSize;
        iTriangle[1] *= iVertexSize;
        iTriangle[2] *= iVertexSize;

        for( UInt j = 0; j < 3; ++j ) {
            iA = iTriangle[j];
            iB = iTriangle[(j+1)%3];
            iC = iTriangle[(j+2)%3];
            pA = (const Vertex4 *)( arrPositions + iA );
            pB = (const Vertex4 *)( arrPositions + iB );
            pC = (const Vertex4 *)( arrPositions + iC );
            pNormA = (const Vector4 *)( arrNormals + iA );
            pNormB = (const Vector4 *)( arrNormals + iB );
            pNormC = (const Vector4 *)( arrNormals + iC );

            // Edge AB, project on tangent plane at A then
            // compute delta of adjacent normals
            vEdge = ( *pB - *pA );
            vProj = vEdge - ( (*pNormA) * (vEdge * (*pNormA)) );
            vDelta = ( (*pNormB) - (*pNormA) );
            for( iRow = 0; iRow < 3; ++iRow ) {
                for( iCol = 0; iCol < 3; ++iCol ) {
                    arrProjTangents[iA](iRow, iCol) += ( vProj[iRow] * vProj[iCol] );
                    arrDeltaTangents[iA](iRow, iCol) += ( vDelta[iRow] * vProj[iCol] );
                }
            }

            // Edge AC, project on tangent plane at A then
            // compute delta of adjacent normals
            vEdge = ( *pC - *pA );
            vProj = vEdge - ( (*pNormA) * (vEdge * (*pNormA)) );
            vDelta = ( (*pNormC) - (*pNormA) );
            for( iRow = 0; iRow < 3; ++iRow ) {
                for( iCol = 0; iCol < 3; ++iCol ) {
                    arrProjTangents[iA](iRow, iCol) += ( vProj[iRow] * vProj[iCol] );
                    arrDeltaTangents[iA](iRow, iCol) += ( vDelta[iRow] * vProj[iCol] );
                }
            }
        }
    }

    // Compute derivate normals
    for( i = 0; i < iVertexCount; ++i ) {
        pNormA = (const Vector4 *)( arrNormals + (i * iVertexSize) );

        // Add N*N^T to W*W^T for numerical stability.
        // In theory 0*0^T is added to D*W^T.
        for( iRow = 0; iRow < 3; ++iRow ) {
            for( iCol = 0; iCol < 3; ++iCol ) {
                arrProjTangents[i](iRow, iCol) *= 0.5f;
                arrProjTangents[i](iRow, iCol) += ( (*pNormA)[iRow] * (*pNormA)[iCol] );
                arrDeltaTangents[i](iRow, iCol) *= 0.5f;
            }
        }

        arrProjTangents[i].Invert( matInverse );
        outDerivateNormals[i] = ( arrDeltaTangents[i] * matInverse );
    }

    // Destroy temp storage
    DeleteA( arrProjTangents );
    DeleteA( arrDeltaTangents );
}
Beispiel #18
0
Void TriangleMesh::UpdateTangentsFromTexCoords( GPUDeferredContext * pContext )
{
    Assert( m_pIL != NULL && m_pVB != NULL );
    Assert( m_pIL->IsBound() && m_pVB->IsBound() );

    Bool bHasNormals = m_pIL->HasField( GPUINPUTFIELD_SEMANTIC_NORMAL, 0 );
    Bool bHasTexCoords = m_pIL->HasField( GPUINPUTFIELD_SEMANTIC_TEXCOORD, 0 );
    if ( !bHasNormals || !bHasTexCoords )
        return;
    Bool bHasTangents =  m_pIL->HasField( GPUINPUTFIELD_SEMANTIC_TANGENT, 0 );
    Bool bHasBiNormals = m_pIL->HasField( GPUINPUTFIELD_SEMANTIC_BINORMAL, 0 );
    if ( !bHasTangents && !bHasBiNormals )
        return;

    // Begin update
    Byte * pFirstVertex = NULL;
    if ( m_pVB->CanUpdate() ) {
        Assert( m_pVB->HasCPUData() );
        pFirstVertex = m_pVB->GetData( m_iVertexOffset );
    } else {
        Assert( m_pVB->CanLock() );
        UInt iByteSize = 0;
        pFirstVertex = (Byte*)( m_pVB->Lock( GPURESOURCE_LOCK_WRITE, 0, &iByteSize, pContext ) );
        Assert( iByteSize == m_pVB->GetSize() );
    }

    // Update
    UInt iVertexSize = m_pVB->GetElementSize();

    UInt iOffset, iSize;
    const Byte * arrPositions = NULL;
    const Byte * arrNormals = NULL;
    const Byte * arrTexCoords = NULL;
    Byte * arrTangents = NULL;
    Byte * arrBiNormals = NULL;

    m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_POSITION, 0 );
    arrPositions = ( pFirstVertex + iOffset );
    m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_NORMAL, 0 );
    arrNormals = ( pFirstVertex + iOffset );
    m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_TEXCOORD, 0 );
    arrTexCoords = ( pFirstVertex + iOffset );
    if ( bHasTangents ) {
        m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_TANGENT, 0 );
        arrTangents = ( pFirstVertex + iOffset );
    }
    if ( bHasBiNormals ) {
        m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_BINORMAL, 0 );
        arrBiNormals = ( pFirstVertex + iOffset );
    }

    UInt i, iTriangleCount = GetTriangleCount();

        // Set all to null vector
    Byte *pCurTangent, *pCurBiNormal;
    Vector4 *pTangent, *pBiNormal;

    if ( bHasTangents ) {
        pCurTangent = arrTangents;
        for( i = 0; i < m_iVertexCount; ++i ) {
            pTangent = (Vector4*)pCurTangent;
            *pTangent = Vector4::Null;
            pCurTangent += iVertexSize;
        }
    } 
    if ( bHasBiNormals ) {
        pCurBiNormal = arrBiNormals;
        for( i = 0; i < m_iVertexCount; ++i ) {
            pBiNormal = (Vector4*)pCurBiNormal;
            *pBiNormal = Vector4::Null;
            pCurBiNormal += iVertexSize;
        }
    }

    // Visit all vertices
    UInt iA, iB, iC;
    const Vertex4 * arrPositionABC[3];
    const Vector4 * arrNormalABC[3];
    const TextureCoord2 * arrTexCoordABC[3];
    Vector4 * arrTangentABC[3];
    Vector4 * arrBiNormalABC[3];  

    UInt j, iNext, iPrev;
    Vector4 vCur;
    Vector4 vNormal, vTangent, vBiNormal;

    for( i = 0; i < iTriangleCount; ++i ) {
        GetTriangle( i, iA, iB, iC );
        iA *= iVertexSize;
        iB *= iVertexSize;
        iC *= iVertexSize;

        arrPositionABC[0] = (const Vertex4 *)( arrPositions + iA );
        arrPositionABC[1] = (const Vertex4 *)( arrPositions + iB );
        arrPositionABC[2] = (const Vertex4 *)( arrPositions + iC );
        arrNormalABC[0] = (const Vector4 *)( arrNormals + iA );
        arrNormalABC[1] = (const Vector4 *)( arrNormals + iB );
        arrNormalABC[2] = (const Vector4 *)( arrNormals + iC );
        arrTexCoordABC[0] = (const TextureCoord2 *)( arrTexCoords + iA );
        arrTexCoordABC[1] = (const TextureCoord2 *)( arrTexCoords + iB );
        arrTexCoordABC[2] = (const TextureCoord2 *)( arrTexCoords + iC );
        if ( bHasTangents ) {
            arrTangentABC[0] = (Vector4 *)( arrTangents + iA );
            arrTangentABC[1] = (Vector4 *)( arrTangents + iB );
            arrTangentABC[2] = (Vector4 *)( arrTangents + iC );
        }
        if ( bHasBiNormals ) {
            arrBiNormalABC[0] = (Vector4 *)( arrBiNormals + iA );
            arrBiNormalABC[1] = (Vector4 *)( arrBiNormals + iB );
            arrBiNormalABC[2] = (Vector4 *)( arrBiNormals + iC );
        }

        for( j = 0; j < 3; ++j ) {
            vCur = ( bHasTangents ) ? *(arrTangentABC[j]) : *(arrBiNormalABC[j]);
            if ( vCur.X != 0.0f || vCur.Y != 0.0f || vCur.Z != 0.0f )
                continue; // already visited

            iNext = (j+1) % 3;
            iPrev = (j+2) % 3;

            // Compute tangent & binormal
            vNormal = *( arrNormalABC[j] );            
            vTangent = _ComputeTexCoordTangent( *(arrPositionABC[j]), *(arrTexCoordABC[j]),
                                                *(arrPositionABC[iNext]), *(arrTexCoordABC[iNext]),
                                                *(arrPositionABC[iPrev]), *(arrTexCoordABC[iPrev]) );
            vTangent -= ( vNormal * (vNormal * vTangent) );
            vTangent.Normalize();
            vBiNormal = ( vNormal ^ vTangent );

            // Update
            if ( bHasTangents )
                *( arrTangentABC[j] ) = vTangent;
            if ( bHasBiNormals )
                *( arrBiNormalABC[j] ) = vBiNormal;
        }
    }

    // End update
    if ( m_pVB->CanUpdate() )
        m_pVB->Update( 0, INVALID_OFFSET, pContext );
    else
        m_pVB->UnLock( pContext );
}
Beispiel #19
0
Void TriangleMesh::UpdateNormals( GPUDeferredContext * pContext )
{
    Assert( m_pIL != NULL && m_pVB != NULL );
    Assert( m_pIL->IsBound() && m_pVB->IsBound() );

    Bool bHasNormals = m_pIL->HasField( GPUINPUTFIELD_SEMANTIC_NORMAL, 0 );
    if ( !bHasNormals )
        return;

    // Begin update
    Byte * pFirstVertex = NULL;
    if ( m_pVB->CanUpdate() ) {
        Assert( m_pVB->HasCPUData() );
        pFirstVertex = m_pVB->GetData( m_iVertexOffset );
    } else {
        Assert( m_pVB->CanLock() );
        UInt iByteSize = 0;
        pFirstVertex = (Byte*)( m_pVB->Lock( GPURESOURCE_LOCK_WRITE, 0, &iByteSize, pContext ) );
        Assert( iByteSize == m_pVB->GetSize() );
    }

    // Update normals
    UInt iVertexSize = m_pVB->GetElementSize();

    UInt iOffset, iSize;
    const Byte * arrPositions = NULL;
    Byte * arrNormals = NULL;

    m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_POSITION, 0 );
    arrPositions = ( pFirstVertex + iOffset );
    m_pIL->GetFieldRange( &iOffset, &iSize, GPUINPUTFIELD_SEMANTIC_NORMAL, 0 );
    arrNormals = ( pFirstVertex + iOffset );

    UInt i, iTriangleCount = GetTriangleCount();

        // Set all normals to null vector
    Byte * pCurNormal = arrNormals;
    Vector4 * pNormal;

    for( i = 0; i < m_iVertexCount; ++i ) {
        pNormal = (Vector4*)pCurNormal;
        pNormal->X = 0.0f;
        pNormal->Y = 0.0f;
        pNormal->Z = 0.0f;
        pCurNormal += iVertexSize;
    }

        // Weighted sum of facet normals
    UInt iA, iB, iC;
    const Vertex4 *pA, *pB, *pC;

    Vector4 vAB, vAC, vFaceNormal;

    for( i = 0; i < iTriangleCount; ++i ) {
        GetTriangle( i, iA, iB, iC );
        iA *= iVertexSize;
        iB *= iVertexSize;
        iC *= iVertexSize;

        pA = (const Vertex4 *)( arrPositions + iA );
        pB = (const Vertex4 *)( arrPositions + iB );
        pC = (const Vertex4 *)( arrPositions + iC );

        vAB = ( *pB - *pA );
        vAC = ( *pC - *pA );
        vFaceNormal = ( vAB ^ vAC );
        vFaceNormal.Normalize();

        pNormal = (Vector4*)( arrNormals + iA );
        *pNormal += vFaceNormal;
        pNormal = (Vector4*)( arrNormals + iB );
        *pNormal += vFaceNormal;
        pNormal = (Vector4*)( arrNormals + iC );
        *pNormal += vFaceNormal;
    }

        // Normalize all again
    pCurNormal = arrNormals;
    for( i = 0; i < m_iVertexCount; ++i ) {
        pNormal = (Vector4*)pCurNormal;
        pNormal->Normalize();
        pCurNormal += iVertexSize;
    }

    // End update
    if ( m_pVB->CanUpdate() )
        m_pVB->Update( 0, INVALID_OFFSET, pContext );
    else
        m_pVB->UnLock( pContext );
}