Skip to content

Commit

Permalink
[ERA-1] ragdoll skinning p2
Browse files Browse the repository at this point in the history
  • Loading branch information
EldarMuradov committed Aug 28, 2024
1 parent 32a69de commit 50efbea
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 94 deletions.
45 changes: 40 additions & 5 deletions modules/core/src/animation/animation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,16 @@ namespace era_engine::animation
}
}

void animation_skeleton::getSkinningMatricesFromGlobalTransforms(const trs* globalTransforms, mat4* outSkinningMatrices, const trs& worldTransform) const
{
uint32 numJoints = (uint32)joints.size();

for (uint32 i = 0; i < numJoints; ++i)
{
outSkinningMatrices[i] = trsToMat4(worldTransform) * trsToMat4(globalTransforms[i]) * joints[i].invBindTransform;
}
}

std::vector<uint32> animation_skeleton::getClipsByName(const std::string& name)
{
std::vector<uint32> result;
Expand Down Expand Up @@ -709,7 +719,7 @@ namespace era_engine::animation

currentGlobalTransforms = 0;

if ((!ragdoll || !ragdoll->simulated) && animation && animation->valid())
if (!ragdoll && animation && animation->valid())
{
auto [vb, skinningMatrices] = skinObject(dxMesh.vertexBuffer, dxMesh.vertexBuffer.positions->elementCount, (uint32)skeleton.joints.size());

Expand Down Expand Up @@ -742,14 +752,39 @@ namespace era_engine::animation
prevFrameVertexBuffer = currentVertexBuffer;
currentVertexBuffer = vb;

static std::vector<trs> transforms = ragdoll->apply();
std::vector<trs> transforms = ragdoll->apply();

skeleton.getSkinningMatricesFromGlobalTransforms(&transforms[0], skinningMatrices);

currentGlobalTransforms = &transforms[0];
}
else if (ragdoll && ragdoll->ragdoll && !ragdoll->simulated)
{
auto [vb, skinningMatrices] = skinObject(dxMesh.vertexBuffer, dxMesh.vertexBuffer.positions->elementCount, (uint32)skeleton.joints.size());

prevFrameVertexBuffer = currentVertexBuffer;
currentVertexBuffer = vb;

trs* localTransforms = arena.allocate<trs>((uint32)skeleton.joints.size());
trs deltaRootMotion;
animation->update(skeleton, dt * timeScale, localTransforms, deltaRootMotion);

for (int i = 0; i < skeleton.joints.size(); ++i)
trs* globalTransforms = arena.allocate<trs>((uint32)skeleton.joints.size());

skeleton.getSkinningMatricesFromLocalTransforms(localTransforms, globalTransforms, skinningMatrices);

if (transform)
{
skinningMatrices[i] = trsToMat4(transforms[i]) * skeleton.joints[i].invBindTransform;
*transform = *transform * deltaRootMotion;
transform->rotation = normalize(transform->rotation);
}

currentGlobalTransforms = &transforms[0];
currentGlobalTransforms = globalTransforms;

ragdoll->updateKinematic();

if (animation->finished)
controller->stateMachine.update();
}
else
{
Expand Down
1 change: 1 addition & 0 deletions modules/core/src/animation/animation.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ namespace era_engine::animation
void getSkinningMatricesFromLocalTransforms(const trs* localTransforms, mat4* outSkinningMatrices, const trs& worldTransform = trs::identity) const;
void getSkinningMatricesFromLocalTransforms(const trs* localTransforms, trs* outGlobalTransforms, mat4* outSkinningMatrices, const trs& worldTransform = trs::identity) const;
void getSkinningMatricesFromGlobalTransforms(const trs* globalTransforms, mat4* outSkinningMatrices) const;
void getSkinningMatricesFromGlobalTransforms(const trs* globalTransforms, mat4* outSkinningMatrices, const trs& worldTransform) const;

std::vector<uint32> getClipsByName(const std::string& name);

Expand Down
84 changes: 59 additions & 25 deletions modules/core/src/px/features/px_ragdoll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ namespace era_engine::physics
shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, true);

mat4 invBindPose = joints[parentIdx].invBindTransform;
mat4 bindPose = joints[parentIdx].bindTransform;
mat4 bindPoseWs = modelWithoutScale * bindPose;

Expand All @@ -85,8 +84,6 @@ namespace era_engine::physics
PxRigidDynamic* body = physics->getPhysics()->createRigidDynamic(px_transform);
body->setActorFlag(PxActorFlag::eVISUALIZATION, true);
body->setMass(mass);
//body->setActorFlag(PxActorFlag::eDISABLE_SIMULATION, true);


body->attachShape(*shape);

Expand Down Expand Up @@ -278,6 +275,8 @@ namespace era_engine::physics
transforms.resize(joints.size());

ragdoll->rigidBodies.resize(joints.size());
ragdoll->childToParentJointDeltaPoses.resize(joints.size());
ragdoll->childToParentJointDeltaRots.resize(joints.size());
ragdoll->relativeJointPoses.resize(joints.size());
ragdoll->originalBodyRotations.resize(joints.size());
ragdoll->bodyPosRelativeToJoint.resize(joints.size());
Expand Down Expand Up @@ -305,7 +304,7 @@ namespace era_engine::physics
j_head_idx,
*ragdoll,
material,
vec3(0.0f, 15.0f * scale, 0.0f),
vec3(0.0f, -5.0f * scale, 0.0f),
4.0f * scale,
skeleton,
modelWithoutScale,
Expand Down Expand Up @@ -456,25 +455,29 @@ namespace era_engine::physics
PxRigidDynamic* body = ragdoll->findRecentBody(i, skeleton, chosenIdx);

PxTransform pxPose = body->getGlobalPose();
mat4 bodyGlobalTransform = trsToMat4(trs{ createVec3(pxPose.p), createQuat(pxPose.q) });
mat4 invBodyGlobalTransform = invert(bodyGlobalTransform);
mat4 bindPoseWs = modelWithoutScale * joints[i].bindTransform;
vec3 jointPosWs = bindPosWs(joints[i].bindTransform, model);
trs bodyGlobalTransform = trs{ createVec3(pxPose.p), createQuat(pxPose.q) };

mat4 bodyPosTransformMat = trsToMat4(bodyGlobalTransform);
mat4 invBodyPosTransformMat = invert(bodyPosTransformMat);

vec4 p = invBodyGlobalTransform * vec4(jointPosWs, 1.0f);
ragdoll->relativeJointPoses[i] = vec3(p.x, p.y, p.z);
ragdoll->originalBodyRotations[i] = mat4ToTRS(bodyGlobalTransform).rotation;
mat4 bindPosWS = modelWithoutScale * skeleton->joints[i].bindTransform;

trs jointTrs = mat4ToTRS(skeleton->joints[i].bindTransform);

ragdoll->relativeJointPoses[i] = (invBodyPosTransformMat * vec4(jointTrs.position, 1.0f)).xyz;
ragdoll->originalBodyRotations[i] = normalize(bodyGlobalTransform.rotation);

if (ragdoll->rigidBodies[i])
{
// Rigid body position relative to the joint
mat4 m = invert(model * joints[i].bindTransform);
p = m * vec4(createVec3(ragdoll->rigidBodies[i]->getGlobalPose().p), 1.0f);

ragdoll->bodyPosRelativeToJoint[i] = vec3(p.x, p.y, p.z);
ragdoll->originalJointRotations[i] = mat4ToTRS(bindPoseWs).rotation;
mat4 m = invert(model * skeleton->joints[i].bindTransform);
ragdoll->bodyPosRelativeToJoint[i] = (m * vec4(bodyGlobalTransform.position, 1.0f)).xyz;
ragdoll->originalJointRotations[i] = normalize(mat4ToTRS(bindPosWS).rotation);
}

ragdoll->childToParentJointDeltaPoses[i] = bodyGlobalTransform.position / scale - jointTrs.position;

ragdoll->childToParentJointDeltaRots[i] = normalize(bodyGlobalTransform.rotation * conjugate(jointTrs.rotation));

finishBody(body, 1.0f, 1.0f);
}

Expand Down Expand Up @@ -548,36 +551,65 @@ namespace era_engine::physics
createD6Joint(l_forearm, l_hand, skeleton, j_hand_l_idx, model);
createD6Joint(r_forearm, r_hand, skeleton, j_hand_r_idx, model);

ragdoll->setKinematic(false);

physics->update(0.016f);

simulated = true;
}

void px_ragdoll_component::updateKinematic()
{
if(!ragdoll->kinematic)
ragdoll->setKinematic(true);

for (int i = 0; i < ragdoll->rigidBodies.size(); ++i)
{
// TODO
PxRigidDynamic* rb = ragdoll->rigidBodies[i];
if (rb)
{
vec3 pos = (model * trsToMat4(transforms[i]) * vec4(ragdoll->bodyPosRelativeToJoint[i], 1.0f)).xyz;

quat jointRot = mat4ToTRS(modelWithoutScale * trsToMat4(transforms[i])).rotation;
quat deltaJRotation = normalize(conjugate(ragdoll->originalJointRotations[i]) * jointRot);

quat rot = normalize(ragdoll->originalBodyRotations[i] * deltaJRotation);

rb->setGlobalPose(PxTransform{createPxVec3(pos), createPxQuat(rot)});
}
}
}

std::vector<trs> px_ragdoll_component::apply(const mat4& modelRotation)
{
using namespace animation;

if (ragdoll->rigidBodies.size() > 0)
{

std::vector<skeleton_joint>& joints = skeleton->joints;

transforms[0] = mat4ToTRS(joints[0].bindTransform);

for (uint32_t i = 1; i < joints.size(); i++)
{
uint32_t chosenIdx = 0;
PxRigidDynamic* body = ragdoll->findRecentBody(i, skeleton, chosenIdx);

mat4 globalTransform = createMat44(body->getGlobalPose());
vec4 globalJointPos = globalTransform * vec4(ragdoll->relativeJointPoses[i], 1.0f);
PxTransform pxPose = body->getGlobalPose();
trs bodyGlobalTransform = trs{ createVec3(pxPose.p), createQuat(pxPose.q) };

vec4 globalJointPos = trsToMat4(bodyGlobalTransform) * vec4(ragdoll->relativeJointPoses[i], 1.0f);

quat bodyRot = mat4ToTRS(globalTransform).rotation;
quat diffRot = conjugate(ragdoll->originalBodyRotations[i]) * bodyRot;
trs jointTrs = mat4ToTRS(skeleton->joints[i].bindTransform);

mat4 translation = trsToMat4(trs(vec3(globalJointPos.x, globalJointPos.y, globalJointPos.z)));
quat deltaRotation = normalize(conjugate(ragdoll->originalBodyRotations[i]) * bodyGlobalTransform.rotation);

quat finalRotation = mat4ToTRS(joints[i].bindTransform).rotation * diffRot;
mat4 rotation = modelRotation * quaternionToMat4(finalRotation);
mat4 translation = trsToMat4(trs{ bodyGlobalTransform.position / scale - ragdoll->childToParentJointDeltaPoses[i], quat::identity});
mat4 rotation = modelRotation * trsToMat4(trs{ vec3(0.0f), jointTrs.rotation * deltaRotation });

transforms[i] = mat4ToTRS(invert(model) * translation * rotation);
transforms[i] = mat4ToTRS(modelWithoutScale * translation * rotation);
}
}

Expand Down Expand Up @@ -624,6 +656,8 @@ namespace era_engine::physics
rigidBodies[i]->wakeUp();
}
}

kinematic = state;
}

}
10 changes: 10 additions & 0 deletions modules/core/src/px/features/px_ragdoll.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,18 @@ namespace era_engine::physics
struct px_ragdoll
{
std::vector<PxRigidDynamic*> rigidBodies;

std::vector<vec3> childToParentJointDeltaPoses;
std::vector<quat> childToParentJointDeltaRots;

std::vector<vec3> relativeJointPoses;
std::vector<quat> originalBodyRotations;

std::vector<vec3> bodyPosRelativeToJoint;
std::vector<quat> originalJointRotations;

bool kinematic = false;

PxRigidDynamic* findRecentBody(uint32_t idx, ref<animation::animation_skeleton> skeleton, uint32_t& chosenIdx);
void setKinematic(bool state);
};
Expand All @@ -35,12 +41,16 @@ namespace era_engine::physics

void initRagdoll(ref<animation::animation_skeleton> skeletonRef);

void updateKinematic();

std::vector<trs> apply(const mat4& modelRotation = mat4::identity);

void update(float dt);

virtual void release(bool releaseActor = false) override;

vec3 worldPosDelta;
quat worldRotDelta;
ref<px_ragdoll> ragdoll = nullptr;
ref<animation::animation_skeleton> skeleton = nullptr;
std::vector<trs> transforms;
Expand Down
Loading

0 comments on commit 50efbea

Please sign in to comment.