D3D Animation Basis(9)

D3D Animation Basis(9)

As for the second draw_mesh function, it skips using the DrawSubset function and uses its own function to render subsets of polygon faces, using the vertex shader and vertex declaration you specify. This second function is extremely useful if you are using vertex shaders to render your meshes.

First, let me show you some helper function usage information:


D3DXATTRIBUTERANGE

Stores an attribute table entry.

typedef struct D3DXATTRIBUTERANGE {
DWORD AttribId;
DWORD FaceStart;
DWORD FaceCount;
DWORD VertexStart;
DWORD VertexCount;
} D3DXATTRIBUTERANGE, *LPD3DXATTRIBUTERANGE;

Members

AttribId
Attribute table identifier.
FaceStart
Starting face.
FaceCount
Face count.
VertexStart
Starting vertex.
VertexCount
Vertex count.

Remarks

An attribute table is used to identify areas of the mesh that need to be drawn with different textures, render states, materials, and so on. In addition, the application can use the attribute table to hide portions of a mesh by not drawing a given attribute identifier (AttribId) when drawing the frame.

The LPD3DXATTRIBUTERANGE type is defined as a pointer to the D3DXATTRIBUTERANGE structure.

typedef D3DXATTRIBUTERANGE* LPD3DXATTRIBUTERANGE;
 

ID3DXBaseMesh::GetAttributeTable

Retrieves either an attribute table for a mesh, or the number of entries stored in an attribute table for a mesh.

HRESULT GetAttributeTable(
D3DXATTRIBUTERANGE * pAttribTable,
DWORD * pAttribTableSize
);

Parameters

pAttribTable
[in, out] Pointer to an array of D3DXATTRIBUTERANGE structures, representing the entries in the mesh's attribute table. Specify NULL to retrieve the value for pAttribTableSize.
pAttribTableSize
[in, out] Pointer to either the number of entries stored in pAttribTable or a value to be filled in with the number of entries stored in the attribute table for the mesh.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.

Remarks

An attribute table is created by ID3DXMesh::Optimize and passing D3DXMESHOPT_ATTRSORT for the Flags parameter.

An attribute table is used to identify areas of the mesh that need to be drawn with different textures, render states, materials, and so on. In addition, the application can use the attribute table to hide portions of a mesh by not drawing a given attribute identifier when drawing the frame.


ID3DXSkinInfo::UpdateSkinnedMesh

Applies software skinning to the target vertices based on the current matrices.

HRESULT UpdateSkinnedMesh(
CONST D3DXMATRIX * pBoneTransforms,
CONST D3DXMATRIX * pBoneInvTransposeTransforms,
LPCVOID pVerticesSrc,
PVOID pVerticesDst
);

Parameters

pBoneTransforms
[in] Bone transform matrix.
pBoneInvTransposeTransforms
[in] Inverse transpose of the bone transform matrix.
pVerticesSrc
[in] Pointer to the buffer containing the source vertices.
pVerticesDst
[in] Pointer to the buffer containing the destination vertices.

Return Values

If the method succeeds, the return value is D3D_OK. If the method fails, the return value can be D3DERR_INVALIDCALL.

Remarks

When used to skin vertices with two position elements, this method skins the second position element with the inverse of the bone instead of the bone itself.

Now, it is implementation of function draw_mesh:

HRESULT draw_mesh(D3DXMESHCONTAINER_EX *  mesh_container,
                  IDirect3DVertexShader9
*  vertex_shader,
                  IDirect3DVertexDeclaration9
*  vertex_decl)
{
    
//  error checking

    
if (mesh_container  ==  NULL  ||  vertex_shader  ==  NULL  ||  vertex_decl  ==  NULL)
        
return  E_FAIL;

    ID3DXMesh
*  mesh  =  mesh_container -> MeshData.pMesh;

    
if (mesh  ==  NULL)
        
return  E_FAIL;

    
if (mesh_container -> NumMaterials  ==   0   ||  mesh_container -> pMaterials  ==  NULL)
        
return  E_FAIL;

    
//  get the device interface
    IDirect3DDevice9 *  device;
    mesh
-> GetDevice( & device);

    DWORD last_alpha_blend, old_alpha_blend, old_src_blend, old_dest_blend;

    
//  Save render states
    device -> GetRenderState(D3DRS_ALPHABLENDENABLE,     & old_alpha_blend);
    device
-> GetRenderState(D3DRS_SRCBLEND,             & old_src_blend);
    device
-> GetRenderState(D3DRS_DESTBLEND,             & old_dest_blend);
    last_alpha_blend 
=  old_alpha_blend;  

    
//  get mesh buffer pointer
    IDirect3DVertexBuffer9 *  vertex_buffer;
    IDirect3DIndexBuffer9
*   index_buffer;
    mesh
-> GetVertexBuffer( & vertex_buffer);
    mesh
-> GetIndexBuffer( & index_buffer);

    
//  get attribute table
    DWORD num_attr;
    mesh
-> GetAttributeTable(NULL,  & num_attr);
    D3DXATTRIBUTERANGE
*  attrs  =   new  D3DXATTRIBUTERANGE[num_attr];
    mesh
-> GetAttributeTable(attrs,  & num_attr);

    
//  use the vertex shader interface passed
    device -> SetFVF( 0 );
    device
-> SetVertexShader(vertex_shader);
    device
-> SetVertexDeclaration(vertex_decl);

    
//  set stream sources
    device -> SetStreamSource( 0 , vertex_buffer,  0 , D3DXGetFVFVertexSize(mesh -> GetFVF()));
    device
-> SetIndices(index_buffer);

    
//  go through each attribute group and render
     for (DWORD i  =   0 ; i  <  num_attr; i ++ )
    {
        
if (attrs[i].FaceCount  !=   0 )
        {
            DWORD mat_index 
=  attrs[i].AttribId;
            device
-> SetTexture( 0 , mesh_container -> textures[mat_index]);

            
//  enable or disable alpha blending per material
             if (mesh_container -> pMaterials[i].MatD3D.Diffuse.a  !=   1.0f )
            {
                
if (last_alpha_blend  !=  TRUE) 
                {
                    last_alpha_blend 
=  TRUE;

                    device
-> SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
                    device
-> SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_ONE);  //  src color
                    device -> SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);
                }
            }
            
else
            {
                
if (last_alpha_blend  !=  FALSE) 
                {
                    last_alpha_blend 
=  FALSE;
                    device
-> SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
                }
            }

            device
-> DrawIndexedPrimitive(D3DPT_TRIANGLELIST,  0 , attrs[i].VertexStart, attrs[i].VertexCount,
                                         attrs[i].FaceStart 
*   3 , attrs[i].FaceCount);
        }
    }

    
//  clear stream uses
    device -> SetStreamSource( 0 , NULL,  0 0 );
    device
-> SetIndices(NULL);

    
//  free resources
    release_com(vertex_buffer);
    release_com(index_buffer);
    delete[] attrs;

    
//  restore alpha blending states
     if (last_alpha_blend  !=  old_alpha_blend) 
    {
        device
-> SetRenderState(D3DRS_ALPHABLENDENABLE, old_alpha_blend);
        device
-> SetRenderState(D3DRS_SRCBLEND,  old_src_blend);
        device
-> SetRenderState(D3DRS_DESTBLEND, old_dest_blend);
    }

    
//  make sure to release the device object!
    device -> Release();

    
//  release vertex shader and declaration mapping
    device -> SetVertexShader(NULL);
    device
-> SetVertexDeclaration(NULL);

    
return  S_OK;
}

 

你可能感兴趣的:(D3D Animation Basis(9))