Esempio n. 1
0
PROTECTED void _MDLOptimize(LPD3DXMESH mesh, const LPD3DXBUFFER pAdjacencyBuffer, int numInd, 
						  LPD3DXMESH *optMesh)
{
	HRESULT hr;
	DWORD        *rgdwAdjacencyTemp = 0;
	LPD3DXMESH	 tempMesh;
	DWORD        dw32Bit = mesh->GetOptions() & D3DXMESH_32BIT;

	// allocate a second adjacency buffer to store post attribute sorted adjacency
	if(MemAlloc((void**)&rgdwAdjacencyTemp, sizeof(DWORD)*numInd, M_ZERO) != RETCODE_SUCCESS)
	{ ASSERT_MSG(0, "Unable to allocate rgdwAdjacencyTemp", "Error in _MDLOptimize"); goto End; }

    // attribute sort - the un-optimized mesh option
    //          remember the adjacency for the vertex cache optimization
    hr = mesh->OptimizeInplace( D3DXMESHOPT_COMPACT|D3DXMESHOPT_ATTRSORT,
                                 (DWORD*)pAdjacencyBuffer->GetBufferPointer(),
                                 rgdwAdjacencyTemp, NULL, NULL);
    if( FAILED(hr) )
        goto End;

    // snapshot the attribute sorted mesh, shown as the un-optimized version
    hr = mesh->CloneMeshFVF( dw32Bit|D3DXMESH_MANAGED, mesh->GetFVF(), 
                                      g_p3DDevice, &tempMesh );
    if( FAILED(hr) )
        goto End;

    // actually do the vertex cache optimization
    hr = mesh->OptimizeInplace( D3DXMESHOPT_COMPACT|D3DXMESHOPT_ATTRSORT|D3DXMESHOPT_VERTEXCACHE,
                                 rgdwAdjacencyTemp,
                                 NULL, NULL, NULL);
    if( FAILED(hr) )
        goto End;

    // snapshot as the optimized mesh
    hr = mesh->CloneMeshFVF( dw32Bit|D3DXMESH_MANAGED, mesh->GetFVF(), 
                                      g_p3DDevice, optMesh );
    if( FAILED(hr) )
        goto End;

End:
	if(rgdwAdjacencyTemp)
		MemFree((void**)&rgdwAdjacencyTemp);
    
	if(tempMesh)
		tempMesh->Release();
}
Esempio n. 2
0
void cMyASELoader::LoadMesh(){
#ifdef _DEBUG
	_ASSERT(m_bLoaded && "Data Not Loaded");
#endif
	int check = 0;
	for (size_t i = 0; i < m_vecASENode.size(); i++){
		if (m_vecASENode[i].nRef != INT_MAX){
			m_vecsubSet.push_back(m_vecASENode[i].nRef);
			LPD3DXMESH pMesh = NULL;
			HRESULT hr = D3DXCreateMeshFVF(m_vecASENode[i].vecVertex.size() / 3,
				m_vecASENode[i].vecVertex.size(),
				D3DXMESH_MANAGED,
				ST_PNT_VERTEX::FVF,
				g_pD3DDevice,
				&pMesh);

			ST_PNT_VERTEX* pV = NULL;
			pMesh->LockVertexBuffer(0, (LPVOID*)&pV);
			memcpy(pV, &m_vecASENode[i].vecVertex[0], m_vecASENode[i].vecVertex.size() * sizeof(ST_PNT_VERTEX));
			pMesh->UnlockVertexBuffer();

			WORD* pI = NULL;
			pMesh->LockIndexBuffer(0, (LPVOID*)&pI);
			for (size_t j = 0; j < pMesh->GetNumVertices(); ++j)
			{
				pI[j] = j;
			}
			pMesh->UnlockIndexBuffer();

			DWORD* pA = NULL;
			pMesh->LockAttributeBuffer(0, &pA);
			for (size_t j = 0; j < pMesh->GetNumFaces(); j++){
				pA[j] = m_vecASENode[i].nRef;
			}
			pMesh->UnlockAttributeBuffer();

			std::vector<DWORD> vecAdjBuffer(m_vecASENode[i].vecVertex.size());
			pMesh->GenerateAdjacency(0.0f, &vecAdjBuffer[0]);

			pMesh->OptimizeInplace(
				D3DXMESHOPT_ATTRSORT |
				D3DXMESHOPT_COMPACT |
				D3DXMESHOPT_VERTEXCACHE,
				&vecAdjBuffer[0], 0, 0, 0);

			m_vecMeshs.push_back(pMesh);
		}
	}
	m_bMeshed = true;
}
Esempio n. 3
0
	void CreateBox( const float &w, const float &h, const float &d, const bool &centerWidth, const bool &centerHeight, const bool &centerDepth, LPD3DXMESH &mesh )
	{
		float offsetX = 0, offsetY = 0, offsetZ = 0;
		if( centerWidth )
			offsetX = -w / 2.f;
		if( centerHeight )
			offsetY = -h / 2.f;
		if( centerDepth )
			offsetZ = -d / 2.f;

		std::vector<DWORD> vIB;
		std::vector<VERTEX3> vVB;
		std::vector<DWORD> vAB;
		DWORD offset = 0;

		// fill in the front face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		// fill in the front face vertex data
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 1.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, 0.f, -1.f, 1.f, 1.f ) );

		vAB.push_back( 0 );
		vAB.push_back( 0 );

		offset += 4;

		// fill in the back face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		// fill in the back face vertex data
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 1.f, 1.f ) );
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, d + offsetZ, 0.f, 0.f, 1.f, 1.f, 0.f ) );

		vAB.push_back( 1 );
		vAB.push_back( 1 );

		offset += 4;

		// fill in the top face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		//fill in the top face vertex data
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 1.f, 0.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, d + offsetZ, 0.f, 1.f, 0.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, d + offsetZ, 0.f, 1.f, 0.f, 1.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, 0.f + offsetZ, 0.f, 1.f, 0.f, 1.f, 1.f ) );

		vAB.push_back( 2 );
		vAB.push_back( 2 );

		offset += 4;

		// fill in the bottom face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		// fill in the bottom face vertex data
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, -1.f, 0.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, 0.f + offsetZ, 0.f, -1.f, 0.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, d + offsetZ, 0.f, -1.f, 0.f, 1.f, 0.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, d + offsetZ, 0.f, -1.f, 0.f, 1.f, 1.f ) );

		vAB.push_back( 3 );
		vAB.push_back( 3 );

		offset += 4;

		// fill in the left face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		// fill in the left face vertex data
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, d + offsetZ, -1.f, 0.f, 0.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, d + offsetZ, -1.f, 0.f, 0.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, h + offsetY, 0.f + offsetZ, -1.f, 0.f, 0.f, 1.f, 0.f ) );
		vVB.push_back( VERTEX3( 0.f + offsetX, 0.f + offsetY, 0.f + offsetZ, -1.f, 0.f, 0.f, 1.f, 1.f ) );

		vAB.push_back( 4 );
		vAB.push_back( 4 );

		offset += 4;

		// fill in the right face index data
		vIB.push_back( 0 + offset );
		vIB.push_back( 1 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 0 + offset );
		vIB.push_back( 2 + offset );
		vIB.push_back( 3 + offset );

		// fill in the right face vertex data
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, 0.f + offsetZ, 1.f, 0.f, 0.f, 0.f, 1.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, 0.f + offsetZ, 1.f, 0.f, 0.f, 0.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, h + offsetY, d + offsetZ, 1.f, 0.f, 0.f, 1.f, 0.f ) );
		vVB.push_back( VERTEX3( w + offsetX, 0.f + offsetY, d + offsetZ, 1.f, 0.f, 0.f, 1.f, 1.f ) );

		vAB.push_back( 5 );
		vAB.push_back( 5 );

		offset += 4;

		D3DXCreateMeshFVF( offset / 2, offset, D3DXMESH_MANAGED | D3DXMESH_32BIT, VERTEX3::FVF, g_pEngine->core->lpd3dd9, &mesh );

		VERTEX3 *pVB = nullptr;
		mesh->LockVertexBuffer( D3DLOCK_DISCARD, reinterpret_cast< void** >( &pVB ) );
		copy( vVB.begin(), vVB.end(), pVB );
		mesh->UnlockVertexBuffer();

		DWORD *pIB = nullptr;
		mesh->LockIndexBuffer( D3DLOCK_DISCARD, reinterpret_cast< void** >( &pIB ) );
		copy( vIB.begin(), vIB.end(), pIB );
		mesh->UnlockIndexBuffer();

		DWORD *pAB = nullptr;
		mesh->LockAttributeBuffer( D3DLOCK_DISCARD, &pAB );
		copy( vAB.begin(), vAB.end(), pAB );
		mesh->UnlockAttributeBuffer();

		std::vector<DWORD> adjacencyBuffer( mesh->GetNumFaces() * 3 );
		mesh->GenerateAdjacency( 0.f, &adjacencyBuffer[ 0 ] );
		mesh->OptimizeInplace( D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, &adjacencyBuffer[ 0 ], nullptr, nullptr, nullptr );
	}
Esempio n. 4
0
//------------------------------------------------------------------------------------------------
// Name:  XMesh
// Desc:  Constructs the subset geometry for a D3DXMesh
//------------------------------------------------------------------------------------------------
bool XMesh::buildGeometryFromD3DXMesh(LPD3DXMESH d3dxMesh, SubsetGeometry* subsetGeometry, DWORD subsets)
{
    // Check parameters
    if (APP_ERROR(!d3dxMesh || !subsetGeometry)("Invalid parameter to XMesh::buildGeometryFromD3DXMesh"))
        return false;

    // Add a reference to the mesh to counteract freeing it at the end
    d3dxMesh->AddRef();

    // Get the device
    LPDIRECT3DDEVICE9 pd3dDevice = NULL;
    d3dxMesh->GetDevice(&pd3dDevice);

    // If this mesh isn't already in the correct format, have D3D do the grunt work of
    // converting it.
    bool generate_normals = false; // Whether or not normals need to be generated for this mesh
    if ((d3dxMesh->GetFVF() != D3DFVF_GEOMETRYVERTEX) ||
        (D3DFMT_GEOMETRYINDEX == D3DFMT_INDEX32) && ((d3dxMesh->GetOptions() & D3DXMESH_32BIT) == 0))
    {
        // Holds the mesh when its converted to the correct format
        LPD3DXMESH pTemd3dxMesh = NULL;

        // Duplicate the loaded mesh into the format
        if (APP_ERROR(d3dxMesh->CloneMeshFVF(
                            D3DXMESH_SYSTEMMEM | ((D3DFMT_GEOMETRYINDEX == D3DFMT_INDEX32) ? D3DXMESH_32BIT : 0),
                            D3DFVF_GEOMETRYVERTEX, pd3dDevice, &pTemd3dxMesh))
                     ("XMesh couldn't convert the source geometry format")) {
            d3dxMesh->Release();
            pd3dDevice->Release();
			      return false;
        }

        // Generate normals if they didn't exist
        generate_normals = ((d3dxMesh->GetFVF()&D3DFVF_NORMAL)!=D3DFVF_NORMAL &&
                            (D3DFMT_GEOMETRYINDEX&D3DFVF_NORMAL)!=D3DFVF_NORMAL);

        // Use this mesh instead
        d3dxMesh->Release();
        d3dxMesh = pTemd3dxMesh;
    }

    // The mesh must have its attributes sorted before it can be converted to single strips
    {
        // Allocate an adjacency buffer
        DWORD faces = d3dxMesh->GetNumFaces();
        DWORD* pAdjacency = new DWORD[faces * 3];
		    bool failed = false;

        if (APP_ERROR(FAILED(d3dxMesh->GenerateAdjacency(ADJACENCY_EPSILON, pAdjacency)))("Unable to generate the mesh adjacency"))
          failed = true;

        { // Clean up "bowties" in the mesh that prevent lighting from being calculated correctly
          LPD3DXMESH cleaned_mesh = NULL;
          DWORD* cleaned_adjacency = new DWORD[faces * 3];
          LPD3DXBUFFER errors_and_warnings = NULL;
          if (!failed && APP_ERROR(FAILED(D3DXCleanMesh(D3DXCLEAN_BOWTIES,
                                                        d3dxMesh,
                                                        pAdjacency,
                                                        &cleaned_mesh,
                                                        cleaned_adjacency,
                                                        &errors_and_warnings)))
                                  ("Failed to clean mesh")) {
            failed = true;
            if (errors_and_warnings) {
              DEBUG_ERROR("Mesh cleaning error:  %s", (const char*)errors_and_warnings->GetBufferPointer());
            }
          }

          SAFE_RELEASE(errors_and_warnings);

          // If we successfully cleaned the mesh, use the new mesh and new set of
          // adjacencies.  Otherwise, just delete anything that was allocated and
          // keep the original.
          if (failed) {
            SAFE_DELETE_ARRAY(cleaned_adjacency);
            SAFE_RELEASE(cleaned_mesh);
          } else {
            SAFE_DELETE_ARRAY(pAdjacency);
            SAFE_RELEASE(d3dxMesh)
            pAdjacency = cleaned_adjacency;
            d3dxMesh = cleaned_mesh;
          }
        }

        // Compute mesh normals, if necessary
        if (!failed && generate_normals && APP_ERROR(FAILED(D3DXComputeNormals(d3dxMesh, pAdjacency)))("Couldn't generate mesh normals")) {
          failed = true;
        }

        // Optimize the mesh
        if (!failed && APP_ERROR(FAILED(d3dxMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT,
                                                                  pAdjacency,
                                                                  NULL,
                                                                  NULL,
                                                                  NULL)))
                                 ("Couldn't optimize mesh attributes")) {
			    failed = true;
		    }

        // Get rid of the temporary adjacency buffer
        SAFE_DELETE_ARRAY(pAdjacency);

        // Return if there was an error
        if (failed) {
          SAFE_RELEASE(d3dxMesh);
          SAFE_RELEASE(pd3dDevice);
          return false;
        }
    }

    // Lock the vertex buffer
    GeometryVertex* pXVertices = NULL;
    if (APP_ERROR(d3dxMesh->LockVertexBuffer(D3DLOCK_READONLY, (VOID**)&pXVertices))("Couldn't lock source vertex buffer"))
    {
		// Erase this mesh
        d3dxMesh->Release();
        pd3dDevice->Release();

		// Failure
		return false;
    }

    // Iterate through all of the materials and copy vertex/index data, and assign material
    // information for the mesh.
    for (DWORD subset = 0; subset < subsets; subset++)
    {
        // Use D3DX to convert this subset into a nicely indexed form
        DWORD numStripIndices;
        LPDIRECT3DINDEXBUFFER9 pSubsetIB;
        if (APP_ERROR(D3DXConvertMeshSubsetToSingleStrip(d3dxMesh, subset, D3DXMESH_SYSTEMMEM, &pSubsetIB, &numStripIndices))("Couldn't convert mesh subset into indexable strip"))
        {
            // Erase any geometry we made
            DeallocateGeometry(subsetGeometry);

            // Get rid of the mesh
            d3dxMesh->UnlockVertexBuffer();
            d3dxMesh->Release();

            // Free our device
            pd3dDevice->Release();

            // Return the error
            return false;
        }

        D3DINDEXBUFFER_DESC desc;
        GeometryIndex* pXIndices = NULL;

        // Check the format of the indices and lock the strip index buffer
        if (APP_ERROR(pSubsetIB->GetDesc(&desc))("Couldn't get .X mesh IB desc") || (desc.Format != D3DFMT_GEOMETRYINDEX) ||
            APP_ERROR(pSubsetIB->Lock(0, 0, (VOID**)&pXIndices, D3DLOCK_READONLY))("Unable to lock the .X index buffer"))
        {
            // Erase any geometry we made
            DeallocateGeometry(subsetGeometry);

            // Get rid of the mesh
            pSubsetIB->Release();
            d3dxMesh->UnlockVertexBuffer();
            d3dxMesh->Release();

            // Free our device
            pd3dDevice->Release();

            // Error!
            return false;
        }

        // This table pairs an index from the .X file to an index in the buffer that
        // holds the vertices for this subset
        XIndicesTable xIndicesTable;

        // For each of the indices in the strip, puts its vertex ID into the indices
        // table.  Use the counter to determine which vertex this is.
        {
            GeometryIndex vertexCounter = 0;
            for (DWORD e = 0; e < numStripIndices; ++e)
            {
                // Insert the entry [x-mesh index, subset index] into the table
                XIndicesTableInsertResult result = xIndicesTable.insert(XIndicesEntry(pXIndices[e], vertexCounter));

                // If the result was successful (this isn't a duplicated X-mesh index) increment the vertex counter
                if (result.second)
                    vertexCounter++;
            }
        }

        // Grab the number of vertices this geometry uses
        DWORD numVertices = (DWORD)xIndicesTable.size();

        // This buffer holds all of the triangles in this subset
        TriangleList triangles;

        // This list keeps track of locations in the strip where the winding order changes.  This is necessary
        // because this next part will remove degenerate triangles from the list.
        std::set<size_t> windingChanges;

        // Generate the list of triangles from the strip provided
        for (DWORD t = 0; t < numStripIndices - 2; ++t)
        {
            // Build the triangle that will be added to the buffer
            // CHANGED July 25, 2008:  the winding order is wrong here
            //Triangle tri = { pXIndices[t + 0], pXIndices[t + 1], pXIndices[t + 2] };
            Triangle tri = { pXIndices[t + 0], pXIndices[t + 2], pXIndices[t + 1] };



            // Convert the triangle into subset-indices by using the lookup table
            // we generated before.
            tri.index[0] = xIndicesTable.find(tri.index[0])->second;
            tri.index[1] = xIndicesTable.find(tri.index[1])->second;
            tri.index[2] = xIndicesTable.find(tri.index[2])->second;

            // Check to make sure this triangle isn't degenerate.  If it is, we can just skip
            // this triangle entirely to simplify the geometry.
            if (tri.index[0] == tri.index[1] || tri.index[1] == tri.index[2] || tri.index[0] == tri.index[2])
            {
                // Try to find the winding in the list
                std::set<size_t>::iterator currentWinding = windingChanges.find(triangles.size());

                // Add this to the winding change list, or remove the change if it's already there
                if (currentWinding != windingChanges.end())
                    windingChanges.erase(currentWinding);
                else
                    windingChanges.insert(triangles.size());

                // Don't insert a triangle here
                continue;
            }

            // Add this triangle to the list
            triangles.push_back(tri);
        }

        // Calculate the number of indices we need for the buffer
        DWORD numGeometryIndices = (DWORD)(triangles.size() * 3);

        // Allocate the destination geometry
        Geometry* pGeometry = NULL;
        if (APP_ERROR(AllocateGeometry(numVertices, numGeometryIndices, &pGeometry))("Couldn't allocate geometry"))
        {
            // Erase any geometry we made
            DeallocateGeometry(subsetGeometry);

            // Get rid of the mesh
            pSubsetIB->Unlock();
            pSubsetIB->Release();
            d3dxMesh->UnlockVertexBuffer();
            d3dxMesh->Release();

            // Free our device
            pd3dDevice->Release();

            // Error!
            return false;
        }

        // Copy the vertices needed for this subset into the buffer
        GeometryVertex* pVertices = pGeometry->pVertices;
        for (XIndicesIterator i = xIndicesTable.begin(); i != xIndicesTable.end(); ++i)
        {
            GeometryVertex* pCurrentVertex = &pVertices[i->second];
            *pCurrentVertex = pXVertices[i->first];

            // Modify the vertex location to make this a unit mesh sitting on the X-Z plane
            pCurrentVertex->x = pCurrentVertex->x;
            pCurrentVertex->y = pCurrentVertex->y;
            pCurrentVertex->z = pCurrentVertex->z;

            //pVertices[i->second].color = D3DCOLOR_XRGB(255,255,255);
            // todo: enable color?
        }

        // Copy triangles into the indices buffer
        DWORD index = 0;
        GeometryIndex* pIndices = pGeometry->pIndices;
        DWORD windingOrder = 0;
        for (TriangleIterator t = triangles.begin(); t != triangles.end(); ++t)
        {
            // Find this index in the winding list
            if (windingChanges.find(index / 3) != windingChanges.end())
                windingOrder = 1 - windingOrder;

            // Alternate the winding order so that everything shows up correctly
            if ((index / 3) % 2 == windingOrder)
            {
                pIndices[index + 0] = t->index[0];
                pIndices[index + 1] = t->index[1];
                pIndices[index + 2] = t->index[2];
            }
            else
            {
                pIndices[index + 0] = t->index[1];
                pIndices[index + 1] = t->index[0];
                pIndices[index + 2] = t->index[2];
            }

            // Increment the index counter
            index += 3;
        }

        // Unlock and delete strip index buffer
        pSubsetIB->Unlock();
        pSubsetIB->Release();

        // Store the buffers in the main array
        std::pair<SubsetGeometry::iterator,bool> result =
            subsetGeometry->insert(SubsetGeometry::value_type(subset, pGeometry));

        if (APP_ERROR(!result.second)("Couldn't insert subset geometry into main array for .X mesh"))
        {
            // Get rid of this geometry
            DeallocateGeometry(pGeometry);
            DeallocateGeometry(subsetGeometry);

            // Erase the mesh
            d3dxMesh->UnlockVertexBuffer();
            d3dxMesh->Release();

            // Free our device
            pd3dDevice->Release();

            // Return error
            return false;
        }

        //DEBUG_MSG("Subset %i has %i vertices %i indices (%i polygons)\n", subset, numVertices, numGeometryIndices, numGeometryIndices / 3);
    }

    // Done with the DirectX mesh.  This will not erase the outside mesh.
    d3dxMesh->UnlockVertexBuffer();
    d3dxMesh->Release();

    // Free the device reference
    pd3dDevice->Release();

    // Success
    return true;
}
Esempio n. 5
0
int main(int argc, char* argv[])
{
	if (argc < 3)
	{
		puts("Usage: MeshConv meshfile rdffile");
		return 1;
	}

	// Initialize DirectDraw
	pD3D = Direct3DCreate9(D3D_SDK_VERSION);
	if (pD3D == NULL)
	{
		puts("Cannot init D3D");
		return 1;
	}

	MeshMender mender;
	std::vector<MeshMender::Vertex> MendVerts;
	std::vector<unsigned int> MendIndices;
	std::vector<unsigned int> mappingNewToOld;

	HRESULT hr;
	D3DDISPLAYMODE dispMode;
	D3DPRESENT_PARAMETERS presentParams;

	pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dispMode);

	ZeroMemory(&presentParams, sizeof(presentParams));
	presentParams.Windowed = TRUE;
	presentParams.hDeviceWindow = GetConsoleWindow();
	presentParams.SwapEffect = D3DSWAPEFFECT_COPY;
	presentParams.BackBufferWidth = 8;
	presentParams.BackBufferHeight = 8;
	presentParams.BackBufferFormat = dispMode.Format;

	hr = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParams, &pD3DDevice);
	if (FAILED(hr))
	{
		printf("Cannot init D3D device: %08x\n", hr);
		pD3D->Release();
		return 1;
	}

	printf("Loading mesh %s: ", argv[1]);

	LPD3DXBUFFER pAdjacency, pMaterials, pEffects;
	DWORD n;
	LPD3DXMESH pLoadMesh;
	hr = D3DXLoadMeshFromX(argv[1], D3DXMESH_SYSTEMMEM, pD3DDevice, &pAdjacency, &pMaterials, &pEffects, &n, &pLoadMesh);
	if (FAILED(hr))
	{
		printf("ERROR: %08x\n", hr);
		goto mesherror;
	}
	pEffects->Release();
	pMaterials->Release();
	printf("%d faces, %d verts\n", pLoadMesh->GetNumFaces(), pLoadMesh->GetNumVertices());

	LPD3DXMESH pMesh;
	if (pLoadMesh->GetFVF() != MESHFVF)
	{
		hr = pLoadMesh->CloneMeshFVF(D3DXMESH_SYSTEMMEM, MESHFVF, pD3DDevice, &pMesh);
		pLoadMesh->Release();
		if (FAILED(hr))
		{
			printf("CloneMesh error: %08x\n", hr);
			goto mesherror;
		}
	}
	else
		pMesh = pLoadMesh;

	printf("Welding verts: ");

	DWORD* pAdj = new DWORD[pAdjacency->GetBufferSize() / 4];

	D3DXWELDEPSILONS Eps;
	memset(&Eps, 0, sizeof(Eps));
	hr = D3DXWeldVertices(pMesh, D3DXWELDEPSILONS_WELDPARTIALMATCHES, &Eps, (DWORD*)pAdjacency->GetBufferPointer(), pAdj, NULL, NULL);
	if (FAILED(hr))
	{
		printf("ERROR: %08x\n", hr);
		goto mesherror;
	}
	
	hr = pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, pAdj, (DWORD*)pAdjacency->GetBufferPointer(), NULL, NULL);
	if (FAILED(hr))
	{
		printf("ERROR: %08x\n", hr);
		goto mesherror;
	}
	
	pAdjacency->Release();
	delete [] pAdj;

	printf("%d faces, %d verts\n", pMesh->GetNumFaces(), pMesh->GetNumVertices());

	printf("Mending mesh: ");

	DWORD NumVerts = pMesh->GetNumVertices();
	DWORD NumFaces = pMesh->GetNumFaces();

	MESHVERT* MeshVert;
	pMesh->LockVertexBuffer(0, (LPVOID*)&MeshVert);

	//fill up Mend vectors with your mesh's data
	MendVerts.reserve(NumVerts);
	for(DWORD i = 0; i < NumVerts; ++i)
	{
		MeshMender::Vertex v;
		v.pos = MeshVert[i].pos;
		v.s = MeshVert[i].s;
		v.t = MeshVert[i].t;
		v.normal = MeshVert[i].norm;
		MendVerts.push_back(v);
	}
	pMesh->UnlockVertexBuffer();

	WORD* MeshIdx;
	pMesh->LockIndexBuffer(0, (LPVOID*)&MeshIdx);

	MendIndices.reserve(NumFaces * 3);
	for(DWORD i = 0; i < NumFaces * 3; ++i)
	{
		MendIndices.push_back(MeshIdx[i]);
	}
	pMesh->UnlockIndexBuffer();

	pMesh->Release();
	pMesh = 0;

	//pass it in to Mend mender to do it's stuff
	mender.Mend(MendVerts, MendIndices, mappingNewToOld, 0.9f, 0.9f, 0.9f, 1.0f, MeshMender::DONT_CALCULATE_NORMALS, MeshMender::RESPECT_SPLITS);
	
	mappingNewToOld.clear();

	printf("%d faces, %d verts\n", MendIndices.size() / 3, MendVerts.size());

	printf("Saving data: ");

	FILE* fp = fopen("meshdata.bin", "wb");
	n = MendIndices.size() / 3;
	fwrite(&n, 4, 1, fp);
	n = MendVerts.size();
	fwrite(&n, 4, 1, fp);
	fclose(fp);

	// Load existing file
	HANDLE hFile = CreateFile(argv[2], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("ERROR: %08x\n", GetLastError());
		goto mesherror;
	}
	DWORD Size = GetFileSize(hFile, 0);
	char* FileData = (char*)VirtualAlloc(0, 64*1024*1024, MEM_RESERVE, PAGE_NOACCESS);
	VirtualAlloc(FileData, Size, MEM_COMMIT, PAGE_READWRITE);
	ReadFile(hFile, FileData, Size, &n, 0);
	FileData[n] = 0;
	Size = n;

	char *p, *q;
	// Find vertex data
	p = strstr(FileData, "VertexBuffer");
	if (!p)
	{
		printf("ERROR: Invalid output file\n");
		goto mesherror;
	}
	p = strchr(p, '{');
	q = p+1;
	int depth = 1;
	do {
		if (*q == '}')
			--depth;
		else if (*q == '{')
			++depth;
		++q;
	} while (depth > 0);

	// move post-vertex data to temp buffer
	Size = (FileData + Size) - q;
	char* TempData = (char*)VirtualAlloc(0, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(TempData, q, Size);

	// write vertex data
	strcpy(p, "{\r\n    VertexFormat {D3DVSDT_FLOAT3 D3DVSDT_NORMPACKED3 D3DVSDT_FLOAT2 D3DVSDT_NORMPACKED3 D3DVSDT_NORMPACKED3}\r\n    VertexData\r\n    {\r\n");
	p += strlen(p);

	for (std::vector<MeshMender::Vertex>::iterator i = MendVerts.begin(); i != MendVerts.end(); ++i)
	{
		VirtualAlloc(p, 500, MEM_COMMIT, PAGE_READWRITE);
		p += sprintf(p, "        %12f %12f %12f  %12f %12f %12f  %12f %12f  %12f %12f %12f  %12f %12f %12f\r\n",
			i->pos.x, i->pos.y, i->pos.z, i->normal.x, i->normal.y, i->normal.z,
			i->s, i->t,
			i->tangent.x, i->tangent.y, i->tangent.z, i->binormal.x, i->binormal.y, i->binormal.z);
	}

	strcpy(p, "    }\r\n}");
	p += strlen(p);

	VirtualAlloc(p, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(p, TempData, Size);
	Size += p - FileData;
	VirtualFree(TempData, 0, MEM_RELEASE);

	// Find index data
	p = strstr(FileData, "IndexBuffer");
	if (!p)
	{
		printf("ERROR: Invalid output file\n");
		goto mesherror;
	}
	p = strchr(p, '{');
	q = p+1;
	depth = 1;
	do {
		if (*q == '}')
			--depth;
		else if (*q == '{')
			++depth;
		++q;
	} while (depth > 0);

	// move post-index data to temp buffer
	Size = (FileData + Size) - q;
	TempData = (char*)VirtualAlloc(0, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(TempData, q, Size);

	// write index data
	strcpy(p, "{\r\n    IndexData\r\n    {\r\n        ");
	p += strlen(p);

	n = 0;
	for (std::vector<unsigned>::iterator i = MendIndices.begin(); i != MendIndices.end(); ++i)
	{
		VirtualAlloc(p, 20, MEM_COMMIT, PAGE_READWRITE);
		p += sprintf(p, " %5hu", *i);
		if (n++ == 2)
		{
			p += sprintf(p, "\r\n       ");
			n = 0;
		}
	}

	strcpy(p-3, "}\r\n}");
	p += strlen(p);

	VirtualAlloc(p, Size, MEM_COMMIT, PAGE_READWRITE);
	memcpy(p, TempData, Size);
	Size += p - FileData;
	VirtualFree(TempData, 0, MEM_RELEASE);

	SetFilePointer(hFile, 0, 0, FILE_BEGIN);
	WriteFile(hFile, FileData, Size, &n, 0);
	SetEndOfFile(hFile);

	CloseHandle(hFile);
	VirtualFree(FileData, 0, MEM_RELEASE);

	printf("Done\n");

	pD3D->Release();
	pD3DDevice->Release();

	return 0;

mesherror:
	pD3D->Release();
	pD3DDevice->Release();
	
	return 1;
}