Exemplo n.º 1
0
ContourPoint * MakeFLPoint(MeshVertex * v0, MeshVertex *v1, Mesh * mesh,
                           const vec3 & cameraCenter,
                           std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint *> & contourPoints)
{
    std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint*>::iterator it =
        contourPoints.find(std::pair<MeshVertex*,MeshVertex*>(v0,v1));

    if (it == contourPoints.end())
        it = contourPoints.find(std::pair<MeshVertex*,MeshVertex*>(v1,v0));

    if (it != contourPoints.end())
        return (*it).second;


    // make the new vertex data.

    ContourPoint * flpt = new ContourPoint();

    flpt->vertex = mesh->NewVertex();

    ParamPointCC newPt;
    FindContour(v0->GetData().sourceLoc, v1->GetData().sourceLoc, cameraCenter, newPt);

    SetupVertex(flpt->vertex->GetData(), newPt, cameraCenter);

    flpt->vertex->GetData().facing = CONTOUR;
    //  flpt->loc = newPt;
    flpt->sourceEdge = v0->GetEdge(v1);

    contourPoints.insert(std::pair<std::pair<MeshVertex*,MeshVertex*>,ContourPoint*>
                         (std::pair<MeshVertex*,MeshVertex*>(v0,v1), flpt));

    return flpt;
}
Exemplo n.º 2
0
// input can be a quad mesh (triangles ok?), output is a triangle mesh
void FlowlineTesselate(Mesh * mesh, const vec3 & cameraCenter)
{
    std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint* > contourPoints;
    std::vector<FlowLinePoint*> childPoints;
    std::multimap<MeshFace*,ContourPoint*> faceMap;

    std::set<MeshFace*> oldContourFaces;

    // each child point has a "stitchVertex" in the original mesh.  some children might share them
    std::map<MeshVertex*,FlowLineCluster*> stitchVertices;
    //  std::multimap<MeshVertex*, FlowLinePoint*> stitchToChildMap;

    // create contour vertices

    std::list<MeshFace*> inputFaces;
    mesh->GetFaces(inputFaces);

    std::vector<FaceRec> newFaces;

    // -------------------  create all the initial contour points --------------------

    for(std::list<MeshFace*>::iterator it = inputFaces.begin(); it != inputFaces.end(); ++it)
    {
        ContourPoint * p[4];
        MeshFace * face = *it;
        int numContourPoints = 0;
        int N = face->GetNumVertices();

        assert(N ==3 || N == 4);

        for(int e=0; e<N; e++)
        {
            MeshVertex * v0 = face->GetVertex(e);
            MeshVertex * v1 = face->GetVertex((e+1)%N);

            assert(v0->GetData().facing != CONTOUR && v1->GetData().facing != CONTOUR);

            if (v0->GetData().facing == v1->GetData().facing)
                continue;

            ContourPoint * flpt = MakeFLPoint(v0,v1,mesh,cameraCenter,contourPoints);
            faceMap.insert(std::pair<MeshFace*,ContourPoint*>(face, flpt));

            p[numContourPoints] = flpt;
            numContourPoints ++;
        }

        assert(numContourPoints == 0 || numContourPoints == 2 || numContourPoints == 4);

        // mark this as a contour face
        if (numContourPoints != 0)
            oldContourFaces.insert(face);

        if (numContourPoints == 4)
            printf("WARNING: QUAD FACE WITH TWO CONTOURS\n");
    }

    // ---------------------- connect contour siblings  -------------------

    for(std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint* >::iterator it = contourPoints.begin();
            it != contourPoints.end(); ++it)
    {
        ContourPoint * flpt = (*it).second;
        MeshEdge * edge = flpt->sourceEdge;
        assert(edge != NULL);  // all contour points lie on edges

        MeshFace * adjFace[2] = { edge->GetLeftFace(), edge->GetRightFace() };

        // connect to siblings

        for(int i=0; i<2; i++)
            if (adjFace[i] != NULL)
            {
                // assuming only 2 points per face

                for(std::multimap<MeshFace*,ContourPoint*>::iterator fit = faceMap.lower_bound(adjFace[i]);
                        fit != faceMap.upper_bound(adjFace[i]); ++fit)
                    if ( (*fit).second != flpt)
                        flpt->AddSibling( (*fit).second);
            }
    }

    // ----------------------- create child points ----------------------------

    for(std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint* >::iterator it = contourPoints.begin();
            it != contourPoints.end(); ++it)
    {
        ContourPoint * flpt = (*it).second;
        //      MeshEdge * edge = flpt->sourceEdge;
        //      assert(edge != NULL);  // all contour points lie on edges

        assert(flpt->nearChild == NULL && flpt->farChild == NULL);

        vec3 viewVec = cameraCenter - flpt->vertex->GetData().pos;

        // create two children
        // trace forward
        ParamRayCC nearRay = flpt->vertex->GetData().sourceLoc.VectorToParamRay(viewVec);
        ParamPointCC nearChildLoc = nearRay.Advance();

        if (!nearChildLoc.IsNull() && nearChildLoc.IsEvaluable())
        {
            //	  assert(nearChildLoc.IsValid());
            flpt->nearChild = new FlowLinePoint();
            flpt->nearChild->vertex = mesh->NewVertex();
            //	  flpt->nearChild->loc = nearChildLoc;
            SetupVertex(flpt->nearChild->vertex->GetData(), nearChildLoc, cameraCenter);
            flpt->nearChild->parent = flpt;
            flpt->nearChild->sourceEdgeVV = nearChildLoc.SourceEdge();

            childPoints.push_back(flpt->nearChild);

            assert(flpt->nearChild->vertex->GetData().facing != CONTOUR);
        }

        // do the same thing, tracing backward
        // trace backward
        ParamRayCC farRay = flpt->vertex->GetData().sourceLoc.VectorToParamRay(-viewVec);
        ParamPointCC farChildLoc = farRay.Advance();
        if (!farChildLoc.IsNull() && farChildLoc.IsEvaluable())
        {
            //	  assert(farChildLoc.IsValid());
            flpt->farChild = new FlowLinePoint();
            flpt->farChild->vertex = mesh->NewVertex();
            //	  flpt->farChild->loc = farChildLoc;
            SetupVertex(flpt->farChild->vertex->GetData(), farChildLoc, cameraCenter);
            flpt->farChild->parent = flpt;
            flpt->nearChild->sourceEdgeVV = nearChildLoc.SourceEdge();
            childPoints.push_back(flpt->farChild);

            assert(flpt->farChild->vertex->GetData().facing != CONTOUR);

            //	  flpt->farChild->sourceEdge = farChildLoc.SourceEdge();
        }
    }

    // ----------------------- connect children to their siblings --------------------

    for(std::vector<FlowLinePoint*>::iterator flit = childPoints.begin(); flit != childPoints.end(); ++flit)
    {
        FlowLinePoint * child = *flit;
        ContourPoint * parent = child->parent;
        for(int i=0; i<child->parent->NumSiblings(); i++)
        {
            ContourPoint * parentSib = parent->siblings[i];
            FlowLinePoint * sib = (child == parent->nearChild ? parentSib->nearChild : parentSib->farChild);
            if (sib != NULL)
                child->AddSibling(sib);
        }
    }


    // ----------------- associate children with stitch vertices ------------------

    for(std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint* >::iterator it = contourPoints.begin();
            it != contourPoints.end(); ++it)
    {
        ContourPoint * flpt = (*it).second;
        MeshEdge * edge = flpt->sourceEdge;
        assert(edge != NULL);  // all contour points lie on edges

        // check if we have a cusp

        // skip cusps and other weird cases for now
        if (flpt->nearChild == NULL || flpt->farChild == NULL ||
                flpt->nearChild->vertex->GetData().facing == flpt->farChild->vertex->GetData().facing)
            continue;

        // find the front-facing/back-facing adjecent vertices of the source mesh to use as stitch vertices
        assert(edge->GetOrgVertex()->GetData().facing != edge->GetDestVertex()->GetData().facing);

        MeshVertex * frontVertex = NULL;
        MeshVertex * backVertex = NULL;

        if (edge->GetOrgVertex()->GetData().facing == FRONT)
        {
            frontVertex = edge->GetOrgVertex();
            backVertex = edge->GetDestVertex();
        }
        else
        {
            frontVertex = edge->GetDestVertex();
            backVertex = edge->GetOrgVertex();
        }

        flpt->nearChild->stitchTarget = (flpt->nearChild->vertex->GetData().facing == FRONT ? frontVertex : backVertex);
        flpt->farChild->stitchTarget =  (flpt->farChild ->vertex->GetData().facing == FRONT ? frontVertex : backVertex);


        if (stitchVertices.find(flpt->nearChild->stitchTarget) == stitchVertices.end())
            stitchVertices[flpt->nearChild->stitchTarget] = new FlowLineCluster();

        FlowLineCluster * nearCluster = stitchVertices[flpt->nearChild->stitchTarget];
        nearCluster->stitchVertex = flpt->nearChild->stitchTarget;
        nearCluster->parents.insert(flpt->nearChild);

        if (stitchVertices.find(flpt->farChild->stitchTarget) == stitchVertices.end())
            stitchVertices[flpt->farChild->stitchTarget] = new FlowLineCluster();

        FlowLineCluster * farCluster = stitchVertices[flpt->farChild->stitchTarget];
        farCluster->stitchVertex = flpt->farChild->stitchTarget;
        farCluster->parents.insert(flpt->farChild);

        //      stitchToChildMap.insert(std::pair<MeshVertex*, FlowLinePoint*>( flpt->nearChild->stitchTarget, flpt->nearChild));
        //      stitchToChildMap.insert(std::pair<MeshVertex*, FlowLinePoint*>( flpt->farChild->stitchTarget, flpt->farChild));
    }


    // ----------------------- generate contour faces -----------------------------

    printf("Num contour points = %d\n", (int)contourPoints.size());

    for(std::map<std::pair<MeshVertex*,MeshVertex*>, ContourPoint*>::iterator it = contourPoints.begin();
            it != contourPoints.end(); ++it)
    {
        ContourPoint * flpt = (*it).second;
        for(int i =0; i<flpt->NumSiblings(); i++)
        {
            if (flpt->nearChild != NULL && flpt->siblings[i]->nearChild != NULL &&
                    flpt->nearChild->vertex->GetEdge(flpt->siblings[i]->nearChild->vertex) == NULL &&
                    flpt->siblings[i]->nearChild->vertex->GetEdge(flpt->nearChild->vertex) == NULL) // not already created
                MakeContourFaces(mesh, flpt, flpt->siblings[i], flpt->nearChild, flpt->siblings[i]->nearChild);

            if (flpt->farChild != NULL && flpt->siblings[i]->farChild != NULL &&
                    flpt->farChild->vertex->GetEdge(flpt->siblings[i]->farChild->vertex) == NULL &&
                    flpt->siblings[i]->farChild->vertex->GetEdge(flpt->farChild->vertex) == NULL)
                MakeContourFaces(mesh, flpt, flpt->siblings[i],flpt->farChild, flpt->siblings[i]->farChild);
        }
    }


    //  -------------------- find the existing mesh vertices to be stitched to this cluster -------

    for(std::map<MeshVertex*,FlowLineCluster*>::iterator it = stitchVertices.begin(); it != stitchVertices.end(); ++it)
    {
        MeshVertex * stitchVertex = (*it).first;
        FlowLineCluster * cluster = (*it).second;

        std::set<MeshFace*> oneRingFaces;
        GetOneRing(stitchVertex, oneRingFaces);

        for(std::set<MeshFace*>::iterator fit = oneRingFaces.begin(); fit != oneRingFaces.end(); ++fit)
            for(int i=0; i< (*fit)->GetNumVertices(); i++)
            {
                MeshVertex * v = (*fit)->GetVertex(i);

                if (v->GetData().facing == stitchVertex->GetData().facing && stitchVertices.find(v) == stitchVertices.end())
                    cluster->existingPoints.insert(v);
            }
    }

    // ---------------------- linearize parents of flowline clusters ------------

    for(std::map<MeshVertex*,FlowLineCluster*>::iterator it = stitchVertices.begin(); it != stitchVertices.end(); ++it)
    {
        FlowLineCluster * cluster = (*it).second;
        std::set<FlowLinePoint*> remainingParents = cluster->parents; // copy the set of parents

        assert (remainingParents.size() > 0);
        FlowLinePoint * start = *(remainingParents.begin());
        remainingParents.erase(remainingParents.begin());
        cluster->parentsOrdered.push_back(start);

        for(int i=0; i<start->NumSiblings(); i++)
        {
            FlowLinePoint * next = start->siblings[i];
            FlowLinePoint * last = start;
            while (remainingParents.find(next) != remainingParents.end())
            {
                remainingParents.erase(remainingParents.find(next));
                if (i == 0)
                    cluster->parentsOrdered.push_back(next);
                else
                    cluster->parentsOrdered.push_front(next);
                if (next->NumSiblings() > 1 && next->siblings[0] != last)
                    next = next->siblings[0];
                else if (next->NumSiblings() > 2 && next->siblings[1] != last)
                    next = next->siblings[1];
                else
                    break;
            }
        }

        if (remainingParents.size() != 0)
            printf("CLUSTER WITH DISCONNECTED PARENTS\n");
        else
            assert(cluster->parents.size() == cluster->parentsOrdered.size());
    }


    // ---------------------- connect flowline clusters to siblings -------------

    for(std::map<MeshVertex*,FlowLineCluster*>::iterator it = stitchVertices.begin(); it != stitchVertices.end(); ++it)
    {
        FlowLineCluster * cluster = (*it).second;

        // skip clusters with disconnected parents
        if (cluster->parents.size() != cluster->parentsOrdered.size())
            continue;

        for(std::set<FlowLinePoint*>::iterator pit = cluster->parents.begin(); pit != cluster->parents.end(); ++pit)
            for(int i=0; i<(*pit)->NumSiblings(); ++i)
            {
                FlowLinePoint * sib = (*pit)->siblings[i];
                if ( sib->stitchTarget != NULL && cluster->parents.find(sib) == cluster->parents.end() &&
                        !cluster->HasSibling(stitchVertices[sib->stitchTarget]))
                    cluster->AddSibling(stitchVertices[sib->stitchTarget], *pit);
            }
    }


    // ----------------------- delete old contour/stitch faces ------------------------
    // note: needed to keep the old faces around long enough for MakeContourFaces to use orientation and to mark the stitch faces

    std::set<MeshFace*> oldStitchFaces;

    for(std::set<MeshFace*>::iterator it = oldContourFaces.begin(); it != oldContourFaces.end(); ++it)
        for(int e=0; e<(*it)->GetNumVertices(); e++)
        {
            MeshFace * left = (*it)->GetEdge(e)->GetLeftFace();
            MeshFace * right = (*it)->GetEdge(e)->GetRightFace();

            if (left != (*it) && oldContourFaces.find(left) == oldContourFaces.end())
                oldStitchFaces.insert(left);

            if (right != (*it) && oldContourFaces.find(right) == oldContourFaces.end())
                oldStitchFaces.insert(right);
        }

    for(std::set<MeshFace*>::iterator it = oldContourFaces.begin(); it != oldContourFaces.end(); ++it)
        mesh->DeleteFace(*it);

    for(std::set<MeshFace*>::iterator fit = oldStitchFaces.begin(); fit != oldStitchFaces.end(); ++fit)
        if ( (*fit) != NULL)
            mesh->DeleteFace(*fit);


    // ---------------------- create connecting faces between flowline clusters ------

    /*  This part crashes
    printf("Creating cluster connecting faces\n");

    std::set<std::pair<FlowLineCluster*,FlowLineCluster*> > visitedPairs;


    for(std::map<MeshVertex*,FlowLineCluster*>::iterator it = stitchVertices.begin(); it != stitchVertices.end(); ++it)
    {
      MeshVertex * stitchVertex = (*it).first;
      FlowLineCluster * cluster = (*it).second;
      for(int i=0;i<cluster->NumSiblings(); i++)
    {
      FlowLineCluster * sibling = cluster->siblings[i];
      if (!sibling->HasSibling(cluster) ||
          visitedPairs.find(std::pair<FlowLineCluster*,FlowLineCluster*>(sibling,cluster)) != visitedPairs.end())
        continue;

      visitedPairs.insert(std::pair<FlowLineCluster*,FlowLineCluster*>(cluster,sibling));

      int oppIndex = (sibling->siblings[0] == cluster ? 0 : 1);

      vector<MeshVertex*> intersection(cluster->existingPoints.size());
      vector<MeshVertex*>::iterator vend;

      // find one or two existing points that these clusters share using a set intersection
      vend = std::set_intersection(cluster->existingPoints.begin(), cluster->existingPoints.end(),
                       sibling->existingPoints.begin(), sibling->existingPoints.end(), intersection.begin());

      // there should be 1 or 2 intersection points
      int intSize = int(vend - intersection.begin());

      if (intSize == 0)  // not sure this can happen; maybe at mesh boundaries or places where tracing went bad
        continue;

      //	  printf("intSize = %d\n", intSize);

      assert(sibling->endpoints[oppIndex]->vertex != cluster->endpoints[i]->vertex);

      if (intSize == 1)
        MakeFaceUnoriented(mesh, cluster->endpoints[i]->vertex, sibling->endpoints[oppIndex]->vertex, intersection[0]);
      else
        {
          assert(intSize == 2);

          MakeFaceUnoriented(mesh, cluster->endpoints[i]->vertex, sibling->endpoints[oppIndex]->vertex, intersection[0], intersection[1]);
        }
    }
    }





    // ----------------------- connect clusters to their own children ("existingPoints") ------------------------------

    for(std::map<MeshVertex*,FlowLineCluster*>::iterator it = stitchVertices.begin(); it != stitchVertices.end(); ++it)
    {
      FlowLineCluster * cluster = (*it).second;

      if (cluster->existingPoints.size() == 0) // huh?
    continue;

      FlowLinePoint* parent = *(cluster->parentsOrdered.begin());

      // make a list of children

      std::list<MeshVertex*> existingOrdered;

      // find a vertex adjacent to the first parent, but along a hole in the mesh. there should be only one...
      MeshVertex * child = NULL;
      std::list<MeshVertex*> oneRing;
      parent->vertex->GetSurroundingVertices(oneRing);

      for(std::list<MeshVertex*>::iterator it = oneRing.begin(); it != oneRing.end(); ++it)
    if ( ((*it)->GetEdge(parent->vertex)==NULL) != (parent->vertex->GetEdge(*it)==NULL) &&
         cluster->existingPoints.find(*it) != cluster->existingPoints.end())
      {
        child = *it;
        break;
      }

      while (child != NULL)
    {
      existingOrdered.push_back(child);
      cluster->existingPoints.erase(cluster->existingPoints.find(child));

      MeshVertex * nextChild = NULL;
      oneRing.clear();
      child->GetSurroundingVertices(oneRing);
      for(std::list<MeshVertex*>::iterator it = oneRing.begin(); it != oneRing.end();++it)
        if ( ((*it)->GetEdge(child)==NULL) != (child->GetEdge(*it)==NULL) &&
         cluster->existingPoints.find(*it) != cluster->existingPoints.end())
          {
        nextChild = *it;
        break;
          }
      child = nextChild;
    }

      // connect up pairs of child and parent into quads

      std::list<FlowLinePoint*>::iterator parentIt = cluster->parentsOrdered.begin();
      std::list<FlowLinePoint*>::iterator nextParentIt;
      std::list<MeshVertex*>::iterator childIt = existingOrdered.begin();
      std::list<MeshVertex*>::iterator nextChildIt;

      nextParentIt = parentIt;
      nextParentIt++;
      nextChildIt = childIt;
      nextChildIt++;

      while (nextParentIt != cluster->parentsOrdered.end() && nextChildIt != existingOrdered.end())
    {
      MakeFaceUnoriented(mesh, (*parentIt)->vertex, (*nextParentIt)->vertex, *childIt, *nextChildIt);
      parentIt ++;
      nextParentIt++;
      childIt ++;
      nextChildIt++;
    }

      // make triangles from any leftovers

      while(nextParentIt != cluster->parentsOrdered.end())
    {
      MakeFaceUnoriented(mesh, (*parentIt)->vertex, (*nextParentIt)->vertex, *childIt);
      parentIt ++;
      nextParentIt++;
    }

      while(nextChildIt != existingOrdered.end())
    {
      MakeFaceUnoriented(mesh, *childIt, *nextChildIt, (*parentIt)->vertex);
      childIt ++;
      nextChildIt++;
    }
    }

    // ----------------------- connect gaps between stitch geometry and original ---------------------

    // TBD
    */



    // ----------------------- convert all remaining quads to triangles ----------------------

    printf("Converting quads to triangles\n");

    std::list<MeshFace*> faces;
    mesh->GetFaces(faces);

    for(std::list<MeshFace*>::iterator it = faces.begin(); it != faces.end(); ++it)
        if ( (*it)->GetNumVertices() == 4)
        {
            MeshFace * face = *it;
            int vID1[3] = { face->GetVertex(0)->GetID(), face->GetVertex(1)->GetID(),  face->GetVertex(2)->GetID() };
            int vID2[3] = { face->GetVertex(0)->GetID(), face->GetVertex(2)->GetID(),  face->GetVertex(3)->GetID() };

            mesh->DeleteFace(face);
            NewFaceDebug(mesh, 3, vID1);
            NewFaceDebug(mesh, 3, vID2);
        }

    // ----------------------- create all new faces ----------------------

    printf("Adding new faces\n");

    for(std::vector<FaceRec>::iterator it = newFaces.begin(); it != newFaces.end(); ++it)
    {
        int IDs[3] = { (*it).v[0]->GetID(), (*it).v[1]->GetID(), (*it).v[2]->GetID() };
        NewFaceDebug(mesh, 3, IDs);
    }

}
Exemplo n.º 3
0
BRUSH* ConvertXModelToBrushFormat ( char* szFilename, BRUSH* pBrush, int* piCount, LPDIRECT3DDEVICE8 lpDevice )
{
	// takes an x model and converts it into brushes

	// check the pointers are valid
	if ( !szFilename || !piCount )
		return NULL;

	// used to access vertex data
	struct sMeshData
	{
		float x, y, z;
		float nx, ny, nz;
		float tu, tv;
	};

	// variable declarations
	tagModelData*			ptr;				// model data
	LPDIRECT3DVERTEXBUFFER8 pMeshVertexBuffer;	// vertex buffer
	LPDIRECT3DINDEXBUFFER8  pMeshIndexBuffer;	// index buffer
	sMeshData*				pMeshVertices;		// mesh vertices
	WORD*					pMeshIndices;		// mesh indices
	sMesh*					pMesh;				// mesh data
	int						iCount;
	
	// load the model
	Constructor ( lpDevice );
	ptr = Load ( 1, szFilename );

	pMesh = ptr->m_Object.m_Meshes;

	// count the number of brushes so we can allocate enough memory for them
	iCount = 0;

	while ( pMesh )
	{
		pMesh = pMesh->m_Next;
		iCount++;
	}

	// store the number of models in the brush count pointer
	*piCount = iCount;

	// now setup the brushes
	pBrush = new BRUSH [ iCount ];	// allocate memory
	
	// set the mesh pointer back to the original mesh
	pMesh = ptr->m_Object.m_Meshes;

	// run through all meshes and store the brush data
	// first off set iCount to 0 so we know which brush
	// we are dealing with
	iCount = 0;

	while ( pMesh )
	{
		int   iInd          = 0;
		DWORD dwNumVertices = pMesh->m_Mesh->GetNumVertices ( );
		DWORD dwNumFaces	= pMesh->m_Mesh->GetNumFaces ( );

		pBrush [ iCount ].Faces      = new POLYGON [ dwNumFaces ];
		pBrush [ iCount ].FaceCount  = dwNumFaces;
		pBrush [ iCount ].Bounds.Max = D3DXVECTOR3 (  150.0f,  150.0f,  150.0f );
		pBrush [ iCount ].Bounds.Min = D3DXVECTOR3 ( -150.0f, -150.0f, -150.0f );
		pBrush [ iCount ].BSPTree    = NULL;

		pMesh->m_Mesh->GetVertexBuffer ( &pMeshVertexBuffer );
		pMesh->m_Mesh->GetIndexBuffer  ( &pMeshIndexBuffer );

		DWORD dwFVF = pMesh->m_Mesh->GetFVF ( );

		pMeshVertexBuffer->Lock ( 0, pMesh->m_Mesh->GetNumVertices  ( ) * sizeof ( sMeshData ), ( BYTE** ) &pMeshVertices, 0 );
		pMeshIndexBuffer->Lock  ( 0, 3 * pMesh->m_Mesh->GetNumFaces ( ) * sizeof ( WORD ),      ( BYTE** ) &pMeshIndices,  0 );
	
		for ( int iTemp = 0; iTemp < dwNumFaces; iTemp++ )
		{
			char szX [ 256 ];
			char szY [ 256 ];
			char szZ [ 256 ];

			int iA = pMeshIndices [ iInd + 0 ];
			int iB = pMeshIndices [ iInd + 1 ];
			int iC = pMeshIndices [ iInd + 2 ];

			WORD wIndices [ ] = { 0, 1, 2 };
			
			pBrush [ iCount ].Faces [ iTemp ].IndexCount   = 3;
			pBrush [ iCount ].Faces [ iTemp ].TextureIndex = 0;
			pBrush [ iCount ].Faces [ iTemp ].VertexCount  = 3;
			pBrush [ iCount ].Faces [ iTemp ].Indices      = new WORD      [ 3 ];
			pBrush [ iCount ].Faces [ iTemp ].Vertices     = new D3DVERTEX [ 3 ];

			pBrush [ iCount ].Faces [ iTemp ].Vertices [ 0 ] = SetupVertex ( pMeshVertices [ iA ].x, pMeshVertices [ iA ].y, pMeshVertices [ iA ].z, pMeshVertices [ iA ].tu, pMeshVertices [ iA ].tv );
			pBrush [ iCount ].Faces [ iTemp ].Vertices [ 1 ] = SetupVertex ( pMeshVertices [ iB ].x, pMeshVertices [ iB ].y, pMeshVertices [ iB ].z, pMeshVertices [ iB ].tu, pMeshVertices [ iB ].tv );
			pBrush [ iCount ].Faces [ iTemp ].Vertices [ 2 ] = SetupVertex ( pMeshVertices [ iC ].x, pMeshVertices [ iC ].y, pMeshVertices [ iC ].z, pMeshVertices [ iC ].tu, pMeshVertices [ iC ].tv );

			for ( int iChar = 0; iChar < 3; iChar++ )
			{
				sprintf ( szX, "%.1f", pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].x );
				sprintf ( szY, "%.1f", pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].y );
				sprintf ( szZ, "%.1f", pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].z );

				pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].x = atof ( szX );
				pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].y = atof ( szY );
				pBrush [ iCount ].Faces [ iTemp ].Vertices [ iChar ].z = atof ( szZ );
			}
			
			memcpy ( pBrush [ iCount ].Faces [ iTemp ].Indices, wIndices, sizeof ( wIndices ) );
			CalculateNormal ( &pBrush [ iCount ].Faces [ iTemp ] );

			iInd += 3;
		}

		SetBlockPosition ( &pBrush [ iCount ], 0.0f, 0.0f, 0.0f, 1.0f );
	
		pMeshVertexBuffer->Unlock ( );
		pMeshIndexBuffer->Unlock  ( );

		iCount++;

		pMesh = pMesh->m_Next;
	}

	iCount = 0;
	pMesh  = ptr->m_Object.m_Meshes;

	for ( int iTemp = ptr->m_Object.m_NumFrames; iTemp > 0; iTemp-- )
	{
		sFrame* pFrame = ptr->m_Object.m_Frames->FindFrame ( iTemp );

		if ( pFrame )
		{
			pBrush [ iCount ].Matrix._41 = pFrame->m_matOriginal._41;
			pBrush [ iCount ].Matrix._42 = pFrame->m_matOriginal._42;
			pBrush [ iCount ].Matrix._43 = pFrame->m_matOriginal._43;

			iCount++;
		}
	}
	
	return pBrush;
}