示例#1
0
void Model::CreateFromSDKMeshFile(ID3D11Device* device, LPCWSTR fileName)
{
    _ASSERT(FileExists(fileName));

    // Use the SDKMesh class to load in the data
    SDKMesh sdkMesh;
    sdkMesh.Create(fileName);

    wstring directory = GetDirectoryFromFileName(fileName);

    // Make materials
    UINT numMaterials = sdkMesh.GetNumMaterials();
    for (UINT i = 0; i < numMaterials; ++i)
    {
        MeshMaterial material;
        SDKMESH_MATERIAL* mat = sdkMesh.GetMaterial(i);
        memcpy(&material.AmbientAlbedo, &mat->Ambient, sizeof(D3DXVECTOR4));
        memcpy(&material.DiffuseAlbedo, &mat->Diffuse, sizeof(D3DXVECTOR4));
        memcpy(&material.SpecularAlbedo, &mat->Specular, sizeof(D3DXVECTOR4));
        memcpy(&material.Emissive, &mat->Emissive, sizeof(D3DXVECTOR4));
        material.Alpha = mat->Diffuse.w;
        material.SpecularPower = mat->Power;
        material.DiffuseMapName = AnsiToWString(mat->DiffuseTexture);
        material.NormalMapName = AnsiToWString(mat->NormalTexture);

        LoadMaterialResources(material, directory, device);

        meshMaterials.push_back(material);
    }

    // Make a D3D9 device
    IDirect3DDevice9Ptr d3d9Device = CreateD3D9Device();

    UINT numMeshes = sdkMesh.GetNumMeshes();
    for (UINT meshIdx = 0; meshIdx < numMeshes; ++meshIdx)
    {
        // Figure out the index type
        UINT ops = D3DXMESH_MANAGED;
        UINT indexSize = 2;
        Mesh::IndexType indexType = Mesh::Index16Bit;
        if (sdkMesh.GetIndexType(meshIdx) == IT_32BIT)
        {
            ops |= D3DXMESH_32BIT;
            indexSize = 4;
            indexType = Mesh::Index32Bit;
        }

        // Make a D3DX mesh
        ID3DXMesh* d3dxMesh = NULL;
        UINT numPrims = static_cast<UINT>(sdkMesh.GetNumIndices(meshIdx) / 3);
        UINT numVerts = static_cast<UINT>(sdkMesh.GetNumVertices(meshIdx, 0));
        UINT vbIndex = sdkMesh.GetMesh(meshIdx)->VertexBuffers[0];
        UINT ibIndex = sdkMesh.GetMesh(meshIdx)->IndexBuffer;
        const D3DVERTEXELEMENT9* vbElements = sdkMesh.VBElements(vbIndex);
        DXCall(D3DXCreateMesh(numPrims, numVerts, ops, vbElements, d3d9Device, &d3dxMesh));
        IUnknownReleaser<ID3DXMesh> meshReleaser(d3dxMesh);

        // Copy in vertex data
        BYTE* verts = NULL;
        BYTE* srcVerts = reinterpret_cast<BYTE*>(sdkMesh.GetRawVerticesAt(vbIndex));
        UINT vbStride = sdkMesh.GetVertexStride(meshIdx, 0);
        UINT declStride = D3DXGetDeclVertexSize(vbElements, 0);
        DXCall(d3dxMesh->LockVertexBuffer(0, reinterpret_cast<void**>(&verts)));
        for (UINT vertIdx = 0; vertIdx < numVerts; ++vertIdx)
        {
            memcpy(verts, srcVerts, declStride);
            verts += declStride;
            srcVerts += vbStride;
        }
        DXCall(d3dxMesh->UnlockVertexBuffer());

        // Copy in index data
        void* indices = NULL;
        void* srcIndices = sdkMesh.GetRawIndicesAt(ibIndex);
        DXCall(d3dxMesh->LockIndexBuffer(0, &indices));
        memcpy(indices, srcIndices, numPrims * 3 * indexSize);
        DXCall(d3dxMesh->UnlockIndexBuffer());

        // Set up the attribute table
        DWORD* attributeBuffer = NULL;
        DXCall(d3dxMesh->LockAttributeBuffer(0, &attributeBuffer));

        UINT numSubsets = sdkMesh.GetNumSubsets(meshIdx);
        D3DXATTRIBUTERANGE* attributes = new D3DXATTRIBUTERANGE[numSubsets];
        ArrayDeleter<D3DXATTRIBUTERANGE> attributeDeleter(attributes);
        for (UINT i = 0; i < numSubsets; ++i)
        {
            SDKMESH_SUBSET* subset = sdkMesh.GetSubset(meshIdx, i);
            attributes[i].AttribId = subset->MaterialID;
            attributes[i].FaceStart = static_cast<DWORD>(subset->IndexStart / 3);
            attributes[i].FaceCount = static_cast<DWORD>(subset->IndexCount / 3);
            attributes[i].VertexStart = static_cast<DWORD>(subset->VertexStart);
            // attributes[i].VertexCount = static_cast<DWORD>(subset->VertexCount);
            attributes[i].VertexCount = numVerts;

            for (UINT faceIdx = attributes[i].FaceStart; faceIdx < attributes[i].FaceStart + attributes[i].FaceCount; ++faceIdx)
                attributeBuffer[faceIdx] = subset->MaterialID;
        }

        DXCall(d3dxMesh->UnlockAttributeBuffer());

        d3dxMesh->SetAttributeTable(attributes, numSubsets);

        // Generate initial adjacency
        vector<DWORD> initialAdjacency;
        initialAdjacency.resize(d3dxMesh->GetNumFaces() * 3);
        DXCall(d3dxMesh->GenerateAdjacency(0.0001f, &initialAdjacency[0]));

        // Make the mesh
        Mesh mesh;
        mesh.CreateFromD3DXMesh(directory, device, d3d9Device, d3dxMesh, false, false, &initialAdjacency[0], indexType);
        meshes.push_back(mesh);
    }
}