void BaseMesh::GenerateNormals()
{
    UINT vc = VertexCount(), ic = IndexCount();
    MeshVertex *V = Vertices();
    DWORD *I = Indices();

    Vec3f V1, V2, Normal;

    for(UINT i = 0; i < vc; i++)
    {
        V[i].Normal = Vec3f::Origin;    //zero each normal
    }

    for(UINT i = 0; i < ic; i += 3)            //for every triangle
    {
        V1 = V[I[i+2]].Pos - V[I[i+0]].Pos;
        V2 = V[I[i+1]].Pos - V[I[i+0]].Pos;
        Normal = Vec3f::Cross(V1, V2);            //compute the triangle normal
        V[I[i+0]].Normal += Normal;
        V[I[i+1]].Normal += Normal;
        V[I[i+2]].Normal += Normal;            //each adjacent vertex adds the triangle normal to its summed normal
    }

    NormalizeNormals();
}
示例#2
0
static void TransformTriMesh( const TQ3Matrix4x4* inMatrix,
								TQ3GeometryObject ioGeom )
{
	TQ3TriMeshData*	tmData = NULL;
	Q3TriMesh_LockData( ioGeom, kQ3False, &tmData );
	
	// Points
	Q3Point3D_To3DTransformArray( tmData->points, inMatrix, tmData->points,
		tmData->numPoints, sizeof(TQ3Point3D), sizeof(TQ3Point3D) );

	// Normal vectors must be transformed by the inverse transpose of the
	// transformation matrix.
	TQ3Matrix4x4	normalTrans;
	Q3Matrix4x4_Invert( inMatrix, &normalTrans );
	Q3Matrix4x4_Transpose( &normalTrans, &normalTrans );
	
	// vertex normal vectors
	TQ3Vector3D*	normals = FindNormals( tmData->vertexAttributeTypes,
		tmData->numVertexAttributeTypes );
	if (normals != NULL)
	{
		Q3Vector3D_To3DTransformArray( normals, &normalTrans, normals,
			tmData->numPoints, sizeof(TQ3Vector3D), sizeof(TQ3Vector3D) );
		NormalizeNormals( normals, tmData->numPoints );
	}

	// face normal vectors
	normals = FindNormals( tmData->triangleAttributeTypes,
		tmData->numTriangleAttributeTypes );
	if (normals != NULL)
	{
		Q3Vector3D_To3DTransformArray( normals, &normalTrans, normals,
			tmData->numTriangles, sizeof(TQ3Vector3D), sizeof(TQ3Vector3D) );
		NormalizeNormals( normals, tmData->numTriangles );
	}
	
	// Recompute the bounding box
	Q3BoundingBox_SetFromPoints3D( &tmData->bBox, tmData->points,
			tmData->numPoints, sizeof(TQ3Point3D) );
	
	// Note: Q3TriMesh_UnlockData will automatically normalize normal vectors.
	Q3TriMesh_UnlockData( ioGeom );
}
示例#3
0
void TMesh::AverageNormals(bool bNormalize)
{
	DEBUG_VERIFY_ALLOCATION;

	size_t i;

	TVertex*		pVertex;
	const TFace*	pFace;

	pVertex = m_Vertices.GetDataPtr();
	for(i = m_Vertices.GetN() ; i ; i--, pVertex++)
		pVertex->m_Normal.Set(0.0f, 0.0f, 0.0f);

	// Summing
	pFace = m_Faces.GetDataPtr();
	for(i = m_Faces.GetN() ; i ; i--, pFace++)
	{
		TVertex& Vertex1 = m_Vertices[pFace->v1];
		TVertex& Vertex2 = m_Vertices[pFace->v2];
		TVertex& Vertex3 = m_Vertices[pFace->v3];

		const TVector3& Coords1 = Vertex1.m_Coords;
		const TVector3& Coords2 = Vertex2.m_Coords;
		const TVector3& Coords3 = Vertex3.m_Coords;

		TVector3 FaceNormal = (Coords2 - Coords1) * (Coords3 - Coords1);

		Vertex1.m_Normal += FaceNormal;
		Vertex2.m_Normal += FaceNormal;
		Vertex3.m_Normal += FaceNormal;
	}

	// Normalizing
	if(bNormalize)
		NormalizeNormals();
}
IFXRESULT CIFXAuthorMeshScrub::Scrub(
								IFXAuthorMesh* pInAuthorMesh,
								IFXAuthorMesh** ppOutAuthorMesh,
								IFXAuthorMeshMap** ppOutMeshMap,
								IFXAuthorMeshScrubParams* pInParams,
								IFXProgressCallback* pInProgressCallback)
{
  IFXRESULT result = IFX_OK;

  if(!pInAuthorMesh || !ppOutAuthorMesh)
  {
    result = IFX_E_INVALID_POINTER;
  }
  /** 
  @todo	FIXME - deallocate any update records -- should ideally be just
		a parameter to the copy call below indicating that no CLOD/update 
		data is to be copied.
  */
  m_pParams = pInParams;
  m_pProgressCallback = pInProgressCallback;

  if(IFXSUCCESS(result) && !m_pParams)
  {
    m_pParams = &s_Params;
  }

  if(IFXSUCCESS(result))
  {
    if(m_pParams->bOperatateInPlace)
    {
      m_pScrubMesh = pInAuthorMesh;
      m_pScrubMesh->AddRef();
    }
    else
    {
      result = pInAuthorMesh->Copy(IID_IFXAuthorMesh,
        (void**)&m_pScrubMesh);
    }
  }

  // Build the mapping table
  if(IFXSUCCESS(result))
  {
    result = IFXCreateComponent(CID_IFXAuthorMeshMap,
      IID_IFXAuthorMeshMap,
      (void **)&m_pMeshMap);
  }

  if(IFXSUCCESS(result))
  {
    result = m_pMeshMap->Allocate(m_pScrubMesh);
  }

  // Get the Mesh Description
  if(IFXSUCCESS(result))
  {
    m_OriginalMeshDesc = *(m_pScrubMesh->GetMaxMeshDesc());
    m_ScrubbedMeshDesc = *(m_pScrubMesh->GetMaxMeshDesc());
  }

  if(IFXSUCCESS(result) && m_pProgressCallback)
  {
    CalcProgressSteps();
  }

  // Allocate Temp storage array
  if(IFXSUCCESS(result) )
  {
    m_TempBufferSize = sizeof(U32) * (
      IFXMAX(m_ScrubbedMeshDesc.NumFaces,
      IFXMAX(m_ScrubbedMeshDesc.NumPositions,
      IFXMAX(m_ScrubbedMeshDesc.NumNormals,
      IFXMAX(m_ScrubbedMeshDesc.NumSpecularColors,
      IFXMAX(m_ScrubbedMeshDesc.NumDiffuseColors,
      IFXMAX(m_ScrubbedMeshDesc.NumTexCoords,
      IFXMAX(m_ScrubbedMeshDesc.NumMaterials,
      m_ScrubbedMeshDesc.NumBaseVertices))))))));

    m_pTempBuffer = new U32[m_TempBufferSize];
  }

  Lock();

  if(IFXSUCCESS(result) && m_pParams->bInvalidIndices)
  {
    result = RemoveInvalidIndices();
    if(IFXSUCCESS(result))
    {
      result = UpdateProgress();
    }
  }

  if(IFXSUCCESS(result) && m_pParams->bZeroAreaFaces)
  {
    result = RemoveZeroAreaFaces();
    if(IFXSUCCESS(result))
    {
      result = UpdateProgress();
    }
  }

  if(IFXSUCCESS(result) && m_pParams->bNormalizeNormals)
  {
    result = NormalizeNormals();
    if(IFXSUCCESS(result))
    {
      result = UpdateProgress();
    }
  }

  if(IFXSUCCESS(result) && m_pParams->bUnusedAttributes)
  {
    if(IFXSUCCESS(result) && m_pParams->RemoveUnusedMaterials)
    {
      result = RemoveUnusedMaterials();
    }

    if(IFXSUCCESS(result) && m_pParams->RemoveUnusedPositions)
    {
      result = RemoveUnusedPositions();
    }

    if(IFXSUCCESS(result) && m_pParams->RemoveUnusedNormals)
    {
      result = RemoveUnusedNormals();
    }

    if(IFXSUCCESS(result) && m_pParams->RemoveUnusedDiffuseColors &&
      m_ScrubbedMeshDesc.NumDiffuseColors)
    {
      result = RemoveUnusedDiffuseColors();
    }

    if(IFXSUCCESS(result) && m_pParams->RemoveUnusedSpecularColors &&
      m_ScrubbedMeshDesc.NumSpecularColors)
    {
      result = RemoveUnusedSpecularColors();
    }

    if(IFXSUCCESS(result) && m_pParams->RemoveUnusedTextureCoordinates &&
      m_ScrubbedMeshDesc.NumTexCoords)
    {
      result = RemoveUnusedTexCoords();
    }

    if(IFXSUCCESS(result))
    {
      result = UpdateProgress();
    }
  }

  // Resize the Scrubbed Mesh - to remove wasted space
  if(IFXSUCCESS(result))
  {
    result = m_pScrubMesh->Reallocate(&m_ScrubbedMeshDesc);
  }

  if(IFXSUCCESS(result))
  {
    result = m_pScrubMesh->SetMeshDesc(m_pScrubMesh->GetMaxMeshDesc());
  }

  if(IFXSUCCESS(result))
  {
    BuildOutputMeshMap();
  }

  Unlock();
  if(IFXSUCCESS(result))
  {
    // Releasing these components is left to the caller
    *ppOutAuthorMesh = m_pScrubMesh;
    *ppOutMeshMap = m_pMeshMap;
  }
  else
  {
    *ppOutAuthorMesh = NULL;
    *ppOutMeshMap = NULL;

    IFXRELEASE(m_pScrubMesh);
    IFXRELEASE(m_pMeshMap);
  }

  IFXDELETE_ARRAY(m_pTempBuffer);
  m_TempBufferSize = 0;

  return result;
}