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.