Rendering Bones on an animated mesh

Started by
8 comments, last by Anddos 12 years, 2 months ago
how do i go about rendering the bones on an animated mesh?, i would like each bone to be a point i think using simple diffuse shader.
:)
Advertisement
I think rendering lines would be more like a bone structure.

but either way is real easy. if you just want points, all you have to do is set the topology to a pointlist, and each bones position is the position of the vertex for each point.

for lines, you would draw a line from the parents position to the childs position, and set the topology to linelist.

So we'll say we have a skeleton that starts at the head (no parent), then shoulders, elbow, then hand, so the vertex list would look like this:

v0.pos = headBone.pos;
v1.pos = shoulderBone.pos;
v2.pos = elbowBone.pos;
v3.pos = handBone.pos;

so for drawing points, just render the vertices above, easy as that. for lines, you will make an index list like this:

0, 1, // head to shoulder line (v0, v1)
1, 2, // shoulder to elbow line (v1, v2)
2, 3 // elbow to hand line (v2, v3)

this way is how you would do it for a joint structure actually. for a bone structure, it is even easier, because each bone specifies two positions, one for each side of the bone
I do it with a set of axes, where each color represents one axis. This tells you all of the information about the joint - its orientation and location with respect to its parent, and the same info for its children too. Here is an example of what I am talking about:

[attachment=7046:SkinAndBones.png]



Also remember to render them after your actual skinned geometry and disable the depth testing to ensure they show up when you render them.
do i need to use transformcoord on each bone matrix?
:)
I don't understand what you mean - can you elaborate on your question?

do i need to use transformcoord on each bone matrix?


1. Just get all matrices that makes up your model / animation and make sure they are in world absolute space (by not multiplaying by inverse bind pose) but only going through the hierarchy and multiplying the local bone matrix by the transformed parent bone matrix.

2. Yes you can now use TransformCoord to transform a point for each matrix to the position where the bone starts, then just add all these points to vertex buffer and render them.

You could easily turn to this into a linelist and draw lines between each bone
Blekinge Institute of Technology
Twitter [twitter]devmoon[/twitter]
Homepage http://devmoon.se
Stream http://twitch.tv/devmoon

[quote name='Anddos' timestamp='1328601283' post='4910436']
do i need to use transformcoord on each bone matrix?


1. Just get all matrices that makes up your model / animation and make sure they are in world absolute space (by not multiplaying by inverse bind pose) but only going through the hierarchy and multiplying the local bone matrix by the transformed parent bone matrix.

2. Yes you can now use TransformCoord to transform a point for each matrix to the position where the bone starts, then just add all these points to vertex buffer and render them.

You could easily turn to this into a linelist and draw lines between each bone
[/quote]

but when creating the vertex buffer at runtime,isnt it expensive to keep locking all the time?
:)
it's only noticeably expensive if you have a large buffer you are updating, or many buffers. Otherwise, theres another way you can update a buffer (but you would want to do this for buffers that are not constantly updated, since the cpu writes are slower, but the gpu reads are faster than using a dynamic buffer, which is the type of buffer you would want if your going to be locking it). You could use ID3D11DeviceContext::UpdateSubresource()
Here is the result , the offsets look way off,

here is the code to update the bones


void update_mesh_containers(CUSTOM_FRAME* pFrame)
{
// cast the pFrame's mesh container pointer to a CUSTOM_MESHCONTAINER*
CUSTOM_MESHCONTAINER* pMeshContainer = (CUSTOM_MESHCONTAINER*)pFrame->pMeshContainer;

if(pMeshContainer && pMeshContainer->pSkinInfo)
{
UINT NumFrames = pMeshContainer->pSkinInfo->GetNumBones(); // find how many frames

//sprintf(outBuffer,"%i\n",NumFrames);
//WriteConsole(Console,outBuffer,strlen(outBuffer),&Written,0);

// for each frame in the mesh container...
for(UINT i = 0; i < NumFrames; i++)
{

// set FinalMatrices to that frame's offset matrix
FinalMatrices = *pMeshContainer->pSkinInfo->GetBoneOffsetMatrix(i);


// multiply that by the animated frame matrix
FinalMatrices *= *pMeshContainer->ppFrameMatrices;

wpoint.createRunTimeWPoint(d3ddev,D3DXVECTOR3(FinalMatrices._41,FinalMatrices._42,FinalMatrices._43),matProjection,matView,matWorlds);

}

void* pSrc = NULL; // a void pointer for the original mesh
void* pDst = NULL; // a void pointer for the modified mesh

// lock the two meshes
pMeshContainer->MeshData.pMesh->LockVertexBuffer(NULL, &pSrc);
pMeshContainer->pFinalMesh->LockVertexBuffer(NULL, &pDst);

// store the animated mesh into FinalMesh
pMeshContainer->pSkinInfo->UpdateSkinnedMesh(FinalMatrices, NULL, pSrc, pDst);

// unlock the two meshes
pMeshContainer->pFinalMesh->UnlockVertexBuffer();
pMeshContainer->MeshData.pMesh->UnlockVertexBuffer();
}

// run for all siblings
if(pFrame->pFrameSibling)
update_mesh_containers((CUSTOM_FRAME*)pFrame->pFrameSibling);

// run for the first child (which will then run all other children)
if(pFrame->pFrameFirstChild)
update_mesh_containers((CUSTOM_FRAME*)pFrame->pFrameFirstChild);
}


here is the point creation code,


void WPoint::createRunTimeWPoint(LPDIRECT3DDEVICE9 d3ddev,D3DXVECTOR3 v1,D3DXMATRIX matProjection,D3DXMATRIX matView,D3DXMATRIX matWorld)
{
CUSTOMVERTEXW_POINT vertices[] =
{
{ v1.x, v1.y, v1.z, D3DCOLOR_XRGB(0, 0, 255), },
};

// create a vertex buffer interface called v_buffer
d3ddev->CreateVertexBuffer(1*sizeof(CUSTOMVERTEXW_POINT),
0,
CUSTOMFVFW_POINT,
D3DPOOL_MANAGED,
&v_buffer,
NULL);

VOID* pVoid; // a void pointer

// lock v_buffer and load the vertices into it
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
v_buffer->Unlock();

if(point_effect_run == NULL)
{
HRESULT hr = D3DXCreateEffectFromFile(d3ddev, "simple.fx", 0, 0, 0, 0, &point_effect_run, &errorlog);
if(FAILED(hr))
{
//MessageBox(NULL,"Shader Failed","",0);
// MessageBox(NULL,(char*)errorlog->GetBufferPointer(),"error",0);
}
else
{
point_effect->FindNextValidTechnique(NULL, &technique);
// MessageBox(NULL,"Shader Created","",0);
}
}
else
{

point_effect_run->SetMatrix("Projection", &matProjection);
point_effect_run->SetMatrix("View", &matView);
point_effect_run->SetMatrix("World", &matWorld);
point_effect_run->Begin(NULL, NULL); // begin using the effect
point_effect_run->BeginPass(0); // begin the pass
d3ddev->SetFVF(CUSTOMFVFW_POINT);
d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEXW_POINT));
d3ddev->DrawPrimitive(D3DPT_POINTLIST, 0, 1);
point_effect_run->EndPass(); // end the pass
point_effect_run->End(); // end the effect
}
}
:)
can anyone help with this problem?
:)

This topic is closed to new replies.

Advertisement