D3D Animation Basis(8)
Drawing Meshes
Now that you have your meshes loaded and you've updated those skinned meshes that needed updating, it is time to throw some pixels at the display and show off those meshes! In total, I have created four mesh−rendering functions to help you in your projects.
HRESULT draw_mesh(D3DXMESHCONTAINER_EX* mesh_container)
{
// error checking
if(mesh_container == NULL)
return E_FAIL;
if(mesh_container->MeshData.pMesh == NULL)
return E_FAIL;
if(mesh_container->NumMaterials == 0 || mesh_container->pMaterials == NULL)
return E_FAIL;
// get the device interface
IDirect3DDevice9* device;
mesh_container->MeshData.pMesh->GetDevice(&device);
// release vertex shader if being used
device->SetVertexShader(NULL);
device->SetVertexDeclaration(NULL);
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;
// setup pointer for mesh to draw, either regular or skinned.
ID3DXMesh* mesh_to_draw = (mesh_container->skin_mesh == NULL) ?
mesh_container->MeshData.pMesh : mesh_container->skin_mesh;
// look through all subsets
for(DWORD i = 0; i < mesh_container->NumMaterials; i++)
{
// set material and texture
device->SetMaterial(&mesh_container->pMaterials[i].MatD3D);
device->SetTexture(0, mesh_container->textures[i]);
// 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);
}
}
mesh_to_draw->DrawSubset(i);
}
// 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();
return S_OK;
}
{
// error checking
if(mesh_container == NULL)
return E_FAIL;
if(mesh_container->MeshData.pMesh == NULL)
return E_FAIL;
if(mesh_container->NumMaterials == 0 || mesh_container->pMaterials == NULL)
return E_FAIL;
// get the device interface
IDirect3DDevice9* device;
mesh_container->MeshData.pMesh->GetDevice(&device);
// release vertex shader if being used
device->SetVertexShader(NULL);
device->SetVertexDeclaration(NULL);
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;
// setup pointer for mesh to draw, either regular or skinned.
ID3DXMesh* mesh_to_draw = (mesh_container->skin_mesh == NULL) ?
mesh_container->MeshData.pMesh : mesh_container->skin_mesh;
// look through all subsets
for(DWORD i = 0; i < mesh_container->NumMaterials; i++)
{
// set material and texture
device->SetMaterial(&mesh_container->pMaterials[i].MatD3D);
device->SetTexture(0, mesh_container->textures[i]);
// 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);
}
}
mesh_to_draw->DrawSubset(i);
}
// 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();
return S_OK;
}
If a material being used specifies an alpha value other than 1, then alpha blending is enabled. This way, you can specify portions of a mesh to use alpha blending by merely changing the material information. Also, if a D3DXMESHCONTAINER_EX object contains a skinned mesh, that mesh is rendered instead of the regular mesh.