I placed the code below, however it is not possible to understand this by anyone than me because I used a lot of my internal functions.
I would prefer to use some ready solution because I am very far from the aim. From theoretical pov it is easy to rectangularize mesh. And in practise it is hard.
I rectangularize vertices of the mesh like they are in x file so not in bone space. I have commented out line (*):
// Get pointer to vertex coordinates
D3DXVECTOR3 *vecPtr = (D3DXVECTOR3*)(pVertices + Vertices[j]*Stride);
// Transform vertex by bone offset transformation, so vertex are in bone space
D3DXVECTOR3 vecPos;
//D3DXVec3TransformCoord(&vecPos, vecPtr, pSkin->GetBoneOffsetMatrix(i)); (*)
vecPos = *vecPtr; //(-)
and use just original vertex coordinates. The effect is the mesh as in the last attached link. If I comment out line (-) and uncomment (*) the effect is as below:
http://img11.imageshack.us/img11/8338/ewzi.jpg
All boxes are placed in one place.
When I run animation then the effect is that boxes are dispersed on the whole screen:
http://img571.imageshack.us/img571/2139/04wj.jpg
This happens with both versions (*) and (-). With version (*) boxes are much more separately. However in each case boxes of animated bones are moving and boxes of not animated bones are not moving.
More code:
void Ragdoll::init(FrameEx* root, MeshContainerEx* meshContainer, IDirect3DDevice9* pDev)
{
if(!root || !meshContainer || !pDev)
{
MessageBox(NULL,"Ragdoll::init() - invalid arguments", "Warning", MB_OK|MB_ICONWARNING);
return;
}
ID3DXSkinInfo *pSkin = meshContainer->pSkinInfo;
u32 numBones = pSkin->GetNumBones();
mBox.resize(numBones);
for(u32 i=0; i<numBones; ++i)
{
const char* boneName = pSkin->GetBoneName(i);
D3DXFRAME* frame = D3DXFrameFind(root, boneName);
if(frame)
{
u32 numVertices = pSkin->GetNumBoneInfluences(i);
if(numVertices)
{
// Get the bone influcences
DWORD *Vertices = new DWORD[numVertices];
float *Weights = new float[numVertices];
pSkin->GetBoneInfluence(i, Vertices, Weights);
// Get stride of vertex data
u32 Stride = meshContainer->mSkinnedMesh->GetNumBytesPerVertex();
// Lock vertex buffer and go through all of the vertices that are connected to bone
char *pVertices = NULL;
meshContainer->mSkinnedMesh->LockVertexBuffer(D3DLOCK_READONLY, (void**)&pVertices);
mBox[i].min.x = d3d::INFINITY;
mBox[i].min.y = d3d::INFINITY;
mBox[i].min.z = d3d::INFINITY;
mBox[i].max.x = -d3d::INFINITY;
mBox[i].max.y = -d3d::INFINITY;
mBox[i].max.z = -d3d::INFINITY;
for(u32 j=0;j<numVertices;++j)
{
// Get pointer to vertex coordinates
D3DXVECTOR3 *vecPtr = (D3DXVECTOR3*)(pVertices + Vertices[j]*Stride);
// Transform vertex by bone offset transformation, so vertex are in bone space
D3DXVECTOR3 vecPos;
//D3DXVec3TransformCoord(&vecPos, vecPtr, pSkin->GetBoneOffsetMatrix(i));
vecPos = *vecPtr;
// Get min/max values
mBox[i].min.x = min(mBox[i].min.x, vecPos.x);
mBox[i].min.y = min(mBox[i].min.y, vecPos.y);
mBox[i].min.z = min(mBox[i].min.z, vecPos.z);
mBox[i].max.x = max(mBox[i].max.x, vecPos.x);
mBox[i].max.y = max(mBox[i].max.y, vecPos.y);
mBox[i].max.z = max(mBox[i].max.z, vecPos.z);
}
meshContainer->mSkinnedMesh->UnlockVertexBuffer();
delete [] Vertices;
delete [] Weights;
}
}
}
if(!mBox.empty())
{
mObject = new Object(pDev);
srand(static_cast<u32>(time(0)));
u32 sumVertices = 0;
u32 sumBones = 0;
for(u32 i=0; i<numBones; ++i)
{
const char* boneName = pSkin->GetBoneName(i);
D3DXFRAME* frame = D3DXFrameFind(root, boneName);
if(frame)
{
u32 numVertices = pSkin->GetNumBoneInfluences(i);
if(numVertices)
{
const D3DMATERIAL9* mat = NULL;
switch(rand()%7)
{
case 0: mat = &material::RED; break;
case 1: mat = &material::GREEN; break;
case 2: mat = &material::BROWN; break;
case 3: mat = &material::BLACK; break;
case 4: mat = &material::WHITE; break;
case 5: mat = &material::BLUE; break;
case 6: mat = &material::YELLOW; break;
}
mObject->set(Szescian,mat,mBox[i].min.x, mBox[i].min.z, mBox[i].min.y, mBox[i].extent().x, mBox[i].extent().z, mBox[i].extent().y, NULL, NULL, MESH);
sumVertices += 8;
mBoneIndices.resize(sumVertices, sumBones);
}
}
++sumBones;
}
if(mObject->createMesh(&D3DXVECTOR3(0,0,0), &mModel, NONEFLAGS, vertNormal2Blending1, NULL, &mBoneIndices) == NOK) //vertNormal2Blending1 //vertNormal2
//if(mObject->createMesh(&D3DXVECTOR3(0,0,0)) == NOK)
MessageBox(NULL,"Ragdoll::init() - new object not created", "Warning", MB_OK|MB_ICONWARNING);
//DWORD vertc = mModel->mesh->GetNumVertices();
//DWORD faces = mModel->mesh->GetNumFaces();
//DWORD bytesPerVert = mModel->mesh->GetNumBytesPerVertex();
//HRESULT hr = mModel->mesh->CloneMeshFVF(D3DXMESH_DYNAMIC | D3DXMESH_32BIT, mModel->mesh->GetFVF(), pDev, &mMeshOryg);
//if(FAILED(hr))
//d3d::CheckError(hr, "CloneMesh(FVF)()");
//vertc = mMeshOryg->GetNumVertices();
//faces = mMeshOryg->GetNumFaces();
//bytesPerVert = mMeshOryg->GetNumBytesPerVertex();
}
}
void Ragdoll::draw(IDirect3DDevice9* pDev, D3DXMATRIX* Finals)
{
VertexShader *vShader = VertexShader::getShaders(Shader::blend1);
vShader->setVertexShader();
vShader->setMatrixArray(Shader::p_F, &Finals[0], static_cast<u32>(mBox.size()));
for(u32 i=0; i<mModel->subsets; ++i)
{
Mtrl mtrl = Mtrl(mModel->material[i]->Ambient, mModel->material[i]->Diffuse, mModel->material[i]->Specular, mModel->material[i]->Power);
vShader->setValue(Shader::p_Mtrl, (void *) &mtrl, sizeof(Mtrl));
D3DXMATRIX mat;
D3DXMatrixIdentity(&mat);
pDev->SetTransform(D3DTS_WORLD, &mat);
mat._41 = 10;
vShader->setMatrix(Shader::p_MatWorld, &mat);
pDev->SetTexture(0, mModel->texture[i]);
//Draw mesh subset
mModel->mesh->DrawSubset(i);
}
vShader->setDefaultVertexShader();
}
My vertex shader code:
uniform extern float4x4 MatWorld; //or uniform extern x, y, z; //not used
uniform extern float4x4 MatWorldInvTrans;
//uniform extern float4x4 MatView; //not used
uniform extern float4x4 MatWVP;
//uniform extern float4x4 MatViewProj; //not used
uniform extern float4x3 F[62]; //Final transformation matrix for each bone (bind space -> root space)
struct Mtrl
{
float4 Ambient;
float4 Diffuse;
float4 Specular; //not used
float Power; //not used
};
struct LightStr
{
float4 Ambient;
float4 Diffuse;
float4 Specular; //not used
float3 Direction; //earlier was float4 and opposite direction (now float3 and also opposite direction)
};
uniform extern Mtrl mtrl;
uniform extern LightStr lightStr;
struct VS_INPUT
{
float3 position : POSITION; //bind space
int boneIndices : BLENDINDICES;
float3 normal : NORMAL;
float2 coord : TEXCOORD;
//float weights : BLENDWEIGHT;
};
struct VS_OUTPUT
{
vector position : POSITION;
vector diffuse : COLOR;
float2 coord : TEXCOORD;
};
VS_OUTPUT Main(VS_INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT)0;
//output position
//Transform root space -> root space acc. to weights
//float3 pos3 = mul(mul(float4(input.position, 1.0f), MatWorld), F[input.boneIndices]);
float3 pos3 = mul(float4(input.position, 1.0f), F[input.boneIndices]);
float4 pos = float4(pos3, 1.0f);
// Transform to homogeneous clip space.
output.position = mul(pos, MatWVP);
//Output diffuse
//Transform root space -> root space acc. to weights
//float3 normal3 = mul(mul(float4(input.normal, 0.0f), MatWorld), F[input.boneIndices]);
float3 normal3 = mul(float4(input.normal, 0.0f), F[input.boneIndices]);
float4 normal = float4(normal3, 0.0f);
// Transform to World space
normal = mul(normal, MatWorldInvTrans);
normal = normalize(normal);
// Light calculation
float4 LightDirection = float4(lightStr.Direction, 0.0f);
float s = dot(LightDirection, normal);
if(s < 0.0f) s = 0.0f; //cosinus <-1,1>
output.diffuse = (mtrl.Ambient * lightStr.Ambient) +
(s * (lightStr.Diffuse * mtrl.Diffuse));
// Forward texture coordinate
output.coord = input.coord;
return output;
}