EDIT: I've got everything working, even animations. This topic can be locked. Also, the file format was very horrible, so I was doing a number of things wrong.
Hello!
I wrote a simple bones system that renders a 3D model with bones using software vertex processing. The model is loaded perfectly, but I can't see any colors on it. For illustration, you can see the 3D lines list, the bones ( 32 bones ) are in correct position ( bind pose ).
Now, here's the problem. When I try to render the mesh with transformations applied then I see this:
As you can see the 3D lines are disappearing, I'm guessing the model is rendered, but the colors are not visible for whatever reason. I tried moving my camera around the line list, but all I can see is some lines disappearing due to the black color of vertices? I'm not loading any textures, am I suppose to load them?
However, if I render the vertices without applying ANY bone transformations, then I can see it, but it's a mess, obviously. If you're wondering why it's red, I have set color of these vertices ( only half of them ) to red and the rest half is white.
First of all, my apologies for the messy code, but here it is:
I'm not sure if vertices are suppose to have weights in them for software vertex processing. I'm storing them in a container, so you don't see them here.
#define CUSTOMFVF ( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE )
struct CUSTOMVERTEX
{
D3DXVECTOR3 Position;
D3DXVECTOR3 Normal;
DWORD Color;
};
This is how I store the vertices in container and give them red and white color:
bool isWhite = true;
for (RwInt32 i = 0; i < TotalVertices; i++)
{
RwV3d * Vertex = VerticesToBlend [ i ];
RwV3d * Normal = NormalsToBlend [ i ];
DWORD color;
isWhite = !isWhite;
if (isWhite)
color = D3DCOLOR_XRGB ( 255, 255, 255 );
else
color = D3DCOLOR_XRGB ( 255, 0, 0 );
CUSTOMVERTEX BlendedVertex = {
D3DXVECTOR3 ( Vertex->X, Vertex->Y, Vertex->Z ),
D3DXVECTOR3 ( Normal->X, Normal->Y, Normal->Z ),
color
};
}
This is how I create the device:
void initializeDirect3D ( HWND hWnd )
{
HRESULT hResult;
Direct3dInterface = Direct3DCreate9(D3D_SDK_VERSION);
if ( !Direct3dInterface )
{
//Handle error
}
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof ( d3dpp ) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
hResult = Direct3dInterface->CreateDevice
(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&Direct3dDevice
);
if (FAILED(hResult))
{
}
Direct3dDevice->SetRenderState ( D3DRS_LIGHTING, FALSE );
Direct3dDevice->SetRenderState ( D3DRS_CULLMODE, D3DCULL_NONE );
Direct3dDevice->SetRenderState ( D3DRS_ZENABLE, TRUE );
}
For every frame:
void renderFrame ( )
{
Direct3dDevice->Clear ( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0 );
Direct3dDevice->BeginScene ( );
updatePipeLine ( );
drawBones2DLines ( );
Direct3dDevice->SetFVF ( CUSTOMFVF );
Direct3dDevice->SetStreamSource(0, VertexBufferTranformed, 0, sizeof(CUSTOMVERTEX));
Direct3dDevice->SetIndices ( IndexBuffer );
BoneMesh * pBoneMesh = PedModel->getBoneMeshPointer ();
// Update Final Transformation Matrix for all bones
for ( size_t i = 0; i < pBoneMesh->Bones.size (); i++ )
{
D3DXMatrixMultiply
(
&pBoneMesh->Bones [ i ].currentBoneMatrix, // Final Transformation Matrix
&pBoneMesh->Bones [ i ].TransformationMatrix, // Offset Matrix ( local tranform )
&pBoneMesh->Bones [ i ].CombinedTransformationMatrix // Combined Matrix
);
}
// Update the skinned mesh
BYTE *src = NULL, *dest = NULL;
VertexBufferOriginal->Lock ( 0, 0, (void**)&src, D3DLOCK_READONLY );
VertexBufferTranformed->Lock ( 0, 0, (void**)&dest, 0 );
PedModel->UpdateSkinnedMesh ( src, dest );
VertexBufferOriginal->Unlock();
VertexBufferTranformed->Unlock();
Geometry * DffGeometry = PedModel->DFFElement->getClump()->getGeometryPointer ( 0 );
RwInt32 TotalVertices = DffGeometry->getTotalVertices ();
RwInt32 TotalTriangles = DffGeometry->getTotalTriangles ();
Direct3dDevice->DrawIndexedPrimitive ( D3DPT_TRIANGLELIST, 0, 0, TotalVertices, 0, TotalTriangles );
Direct3dDevice->EndScene ( );
Direct3dDevice->Present ( NULL, NULL, NULL, NULL );
}
This is the UpdateSkinnedMesh method:
void Ped::UpdateSkinnedMesh ( const void * src_vertices, void * dst_vertices )
{
const std::vector < RwUInt8V4d * > & VertexBoneIndices = pSkinPLG->getVertexBoneIndices ();
const std::vector < RwMatrixWeights * > & VertexWeights = pSkinPLG->getVertexBoneWeights ();
for ( RwInt32 VertexIndex = 0; VertexIndex < TotalVertices; VertexIndex ++ )
{
D3DXVECTOR3 * SourcePosition = (D3DXVECTOR3*)((BYTE*)src_vertices + sizeof(CUSTOMVERTEX) * VertexIndex );
D3DXVECTOR3 * DestinationPosition = (D3DXVECTOR3*)((BYTE*)dst_vertices + sizeof(CUSTOMVERTEX) * VertexIndex );
D3DXVECTOR3 * SourceNormal = (D3DXVECTOR3*)((BYTE*)src_vertices +
( sizeof ( CUSTOMVERTEX ) * VertexIndex ) + sizeof ( D3DXVECTOR3 ) );
D3DXVECTOR3 * DestinationNormal = (D3DXVECTOR3*)((BYTE*)dst_vertices +
( sizeof ( CUSTOMVERTEX ) * VertexIndex ) + sizeof ( D3DXVECTOR3 ) );
/* Reset position */
memset ( DestinationPosition, 0, sizeof ( D3DXVECTOR3 ) );
/* Reset normal */
memset (DestinationNormal, 0, sizeof ( D3DXVECTOR3 ) );
RwUInt8V4d * pVertexBoneIndices = VertexBoneIndices [ VertexIndex ];
RwMatrixWeights * pVertexWeights = VertexWeights [ VertexIndex ];
for (DWORD i = 0; i < 4; i++)
{
Bone * pBone = getBonePointerByIndex ( pVertexBoneIndices->Element[i] );
// Final Transformation Matrix
const D3DXMATRIX & CurrentBoneMatrix = getCurrentBoneMatrixReference ( pVertexBoneIndices->Element [i] );
// Offset Matrix
const D3DXMATRIX & TransformationBoneMatrix = getTransformationBoneMatrixReference ( pVertexBoneIndices->Element[i] );
//Inverse Bone Matrix
D3DXMATRIX bone_inverse;
D3DXMATRIX matrix;
// I tried taking inverse of both Offset Matrix and Combined Matrix
D3DXMatrixInverse(&bone_inverse, NULL, &TransformationBoneMatrix);
//D3DXMatrixInverse(&bone_inverse, NULL, &pBone->CombinedTransformationMatrix);
D3DXMatrixMultiply(&matrix, &CurrentBoneMatrix, &bone_inverse);
D3DXMatrixMultiply(&matrix, &matrix, &TransformationBoneMatrix);
D3DXVECTOR3 position;
D3DXVec3TransformCoord ( &position, SourcePosition, &matrix );
DestinationPosition->x += pVertexWeights->weights [ i ] * position.x;
DestinationPosition->y += pVertexWeights->weights [ i ] * position.y;
DestinationPosition->z += pVertexWeights->weights [ i ] * position.z;
D3DXVECTOR3 normal;
D3DXMATRIX matrix_normal;
D3DXMatrixMultiply(&matrix_normal, &TransformationBoneMatrix, &CurrentBoneMatrix);
D3DXVec3TransformNormal(&normal, SourceNormal, &bone_inverse);
D3DXVec3TransformNormal(&normal, &normal, &matrix_normal);
DestinationNormal->x += pVertexWeights->weights [ i ] * normal.x;
DestinationNormal->y += pVertexWeights->weights [ i ] * normal.y;
DestinationNormal->z += pVertexWeights->weights [ i ] * normal.z;
}
if ((DestinationNormal->x != 0.0f) && (DestinationNormal->y != 0.0f) && (DestinationNormal->z != 0.0f))
{
D3DXVec3Normalize ( DestinationNormal, DestinationNormal );
}
}
}
I have debugged bone weights and bone indices. They are okay. Bone weights add up to 1.0f, so I'm really wondering why I can't see the model with colors on it?