Jump to content
  • Advertisement
Sign in to follow this  
ayush3017

Ragdoll wrong transformation matrix ruins skinned mesh

This topic is 2775 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Its a DirectX matrix question so I thought this section is appropriate. Ok, here is the problem I was about to complete my game but then my mind demanded more so I thought of applying ragdolls in my game:
1. My game uses nVIDIA PhysX engine.
2. Im currently using hardware skinning.
3. I create my ragdoll using box shapes.
4. The ragdoll creation is ok as I have tested it in Visual debugger.
5. After applying ragdoll I get the transforms of each actor and apply it directly to the skinned mesh. So here is the problem. After applying this my mesh is not drawn correctly. I know that you cannot just apply directly the transforms to the bones but here Im totally clueless. Here are the screens:
Ragdoll switched off
Ragdoll on

And here is the code of ragdoll creation:


void peds::CreateRagdoll()
{
NxQuat qRotLeft, qRotRight, qRotAround;
qRotLeft.fromAngleAxis(90, NxVec3(0,0,1));
qRotRight.fromAngleAxis(-90, NxVec3(0,0,1));
qRotAround.fromAngleAxis(180, NxVec3(0,0,1));
transformation.resize(player.pedsMesh.NumBones());

ragdollActors.resize(player.pedsMesh.NumBones());
//boxMeshes.resize(player.pedsMesh.NumBones());

//Get current bone transforms from skinned mesh and make ragdoll actors
//depending upon the transforms
vector<D3DXMATRIX> a = player.pedsMesh.getTransforms();

//Disable character controller collision
player.pedsMesh.playerController->getActor()->raiseActorFlag(NX_AF_DISABLE_COLLISION);

//-----
///Create Ragdoll Actors////
//-----
/Code removed


for(int x=0 ; x< player.pedsMesh.NumBones() ; x++)
{
NxMat34 b;
b.setColumnMajor44(a[x]);

ragdollActors[x]->setGlobalPosition(b.t);
ragdollActors[x]->setSolverIterationCount(50);
}

//Create Actors
//COde removed


//Transform the ragdoll created to current player position
for(int x=0 ; x<player.pedsMesh.NumBones() ; x++)
{


D3DXMatrixMultiply(&a[x], &a[x], &player.pedsMesh.wowMatrix);
NxMat34 b;
b.setColumnMajor44(a[x]);
ragdollActors[x]->setGlobalPosition(b.t);
ragdollActors[x]->putToSleep();
}
}



Code fo getting actor transforms and applying it to skinned mesh:



if(!ragdollAvailable)
{
//Get current player matrix and apply it to world matrix
effect->SetMatrix("world", &player.pedsMesh.wowMatrix);
//Get bone transforms
effect->SetMatrixArray("gFinalXForms", player.pedsMesh.getFinalXFormArray(), player.pedsMesh.NumBones());
}
else
{

effect->SetMatrix("world", &worldMatrix);
//Get actor transforms and apply it to skined mesh
//<-- This is the wrong stuff --->
for(int x=0 ; x<player.pedsMesh.NumBones() ; x++)
{
// Get actors global pose in world space
ragdollActors[x]->getGlobalPose().getColumnMajor44(transformation[x]);
D3DXMatrixScaling(&scale, 2.5f, 2.5f, 2.5f);
D3DXMatrixMultiply(&transformation[x], &scale, &transformation[x]);
}

//effect->SetMatrix("world", &scale);
effect->SetMatrixArray("gFinalXForms", &transformation[0], player.pedsMesh.NumBones());

}




And here is the most common skinning shader code !


float4x4 world;
float4x4 view;
float4x4 projection;
float3 eyePos;
float4x4 InverseTransposeView;

uniform extern float4x4 gFinalXForms[35];

texture colorMap;
sampler colorMapSampler = sampler_state
{
Texture = <colorMap>;
MinFilter = Anisotropic;
MagFilter = Linear;
MipFilter = Linear;
MaxAnisotropy = 16;
};

struct OutputVS
{
float4 vPos : POSITION0;
float2 vTex0 : TEXCOORD0;
float3 vWorldPos : TEXCOORD1;
float3 vWorldNrm : TEXCOORD2;
float3 eyeVec : TEXCOORD3;
float4 vPos1 : TEXCOORD4;
};


struct OutputPS
{
float4 vMaterial : COLOR0;
float4 vWorldNrm : COLOR1;
float4 vWorldPosXY : COLOR2;
};

OutputVS VS_Lambert(float3 posL : POSITION0,
float3 tangentL : TANGENT0,
float3 binormalL : BINORMAL0,
float3 normalL : NORMAL0,
float2 tex0 : TEXCOORD0,
float4 weight0 : BLENDWEIGHT0,
float4 boneIndex : BLENDINDICES)
{

OutputVS outVS = (OutputVS)0;

float4 vertex = float4(posL, 1);
float LastWeight = 0.0f;
float4 p = 0.0f;
float4 n = 0.0f;

float BlendWeightsArray[4] = (float[4])weight0;
int4 IndexVector = D3DCOLORtoUBYTE4(boneIndex);
int IndexArray[4] = (int[4])IndexVector;


for(int x=0 ; x<3 ; x++)
{
LastWeight = LastWeight + BlendWeightsArray[x];
p += BlendWeightsArray[x] * mul(float4(posL, 1.0f), gFinalXForms[IndexArray[x]]);
n += BlendWeightsArray[x] * mul(float4(normalL, 0.0f), gFinalXForms[IndexArray[x]]);

}

LastWeight = 1.0f - LastWeight;
p += LastWeight * mul(float4(posL, 1.0f), gFinalXForms[IndexArray[3]]);
n += LastWeight * mul(float4(normalL, 0.0f), gFinalXForms[IndexArray[3]]);

// p.w = 1.0f;
//n.w = 0.0f;




n = normalize(n);


float4x4 ViewSpace = mul(world, view);
outVS.vWorldPos = mul(p, ViewSpace);
float3 vWorldPos = mul(p, ViewSpace);
outVS.eyeVec = p.xyz - eyePos;
float4x4 viewProjection = mul(view, projection);
outVS.vPos = mul(float4(outVS.vWorldPos, 1), projection);
outVS.vPos1 = outVS.vPos;
outVS.vTex0 = tex0;

outVS.vWorldNrm = normalize(mul(n, (float3x3) InverseTransposeView));

return outVS;
}

//-----------------------------------------------------------------------------
// Pixel shader.
//-----------------------------------------------------------------------------


OutputPS PS_Lambert(OutputVS i) : COLOR
{
OutputPS o;

float distance1 = distance(i.eyeVec, float3(0, 0, 0));

float4 texColor = tex2D(colorMapSampler, i.vTex0);

distance1 /= 460;

//LOD alpha transition
//clip(texColor - distance1/2);

//clip(texColor.a - 0.2f);


//clip(texColor.a - 0.5f);
o.vMaterial.rgb = texColor * 1.5f;
//o.vMaterial.rgb = float3(0.6f, 0.6f, 0.6f);
o.vMaterial.a = texColor.a;

o.vWorldNrm.xyz = 0.5f * (i.vWorldNrm + 1.0f);
o.vWorldNrm.w = 0.0;

o.vWorldPosXY = float4(i.vWorldPos.xyz, 0);


return o;
}



What should I do to correctly transform my skinned mesh??
Thanks.

Share this post


Link to post
Share on other sites
Advertisement
I think I should change my question: How to get transformation from rigid bodies (ragdoll actors) and apply it correctly to skinned mesh??

Share this post


Link to post
Share on other sites
Hi, I lost the reply refreshing by mistake the current page, the main idea is that actors are in world space, and the bone are in bone space, that's why you get that weird results, use the offset matrix of each bone to set to world space, now you can transform with the actors orientation, and make sure to set actor matrix translation to zero to keep connected the bones, because the actor local axis may or may not be the same of the mesh bone.

ActorMatrix - 4° row to zero
OFFSETMATRIX - Offset bone Matrix
BONEMATRIX - Bone Matrix, transformed by his parents.

M' = OFFSETMATRIX*BONEMATRIX;
FMATRIX = M'*ActorMatrix;

I had the same problem, is just make clear what is on bone space and what is on world space, my results:



If you still have issues you can addme to msn: camus_mm@hotmail.com

Share this post


Link to post
Share on other sites
Hi, I lost the reply refreshing by mistake the current page, the main idea is that actors are in world space, and the bone are in bone space, that's why you get that weird results, use the offset matrix of each bone to set to world space, now you can transform with the actors orientation, and make sure to set actor matrix translation to zero to keep connected the bones, because the actor local axis may or may not be the same of the mesh bone.

ActorMatrix - 4° row to zero
OFFSETMATRIX - Offset bone Matrix
BONEMATRIX - Bone Matrix, transformed by his parents.

M' = OFFSETMATRIX*BONEMATRIX;
FMATRIX = M'*ActorMatrix;

I had the same problem, is just make clear what is on bone space and what is on world space, my results:



If you still have issues you can addme to msn: camus_mm@hotmail.com

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!