void RagdollAnimNode::BlendState (csSkeletalState2* state, float baseWeight) { if (!isActive) return; //printf ("RagdollAnimNode::BlendState\n"); // TODO: use baseWeight for (csHash<Bone, BoneID>::GlobalIterator it = bones.GetIterator (); it.HasNext(); ) { Bone bone = it.Next (); csOrthoTransform bodyTransform = bone.rigidBody->GetTransform (); // TODO: test for deactivation of rigid body BoneID parentBoneID = skeleton->GetFactory ()->GetBoneParent (bone.boneID); // if this bone is the root of the skeleton // TODO: valid also for root of dynamic node? if (parentBoneID == InvalidBoneID) { csQuaternion boneRotation; csVector3 boneOffset; skeleton->GetFactory ()->GetTransformBoneSpace (bone.boneID, boneRotation, boneOffset); csOrthoTransform boneTransform (csMatrix3 (boneRotation), boneOffset); csOrthoTransform newTransform = boneTransform.GetInverse () * bodyTransform; iMovable* movable = sceneNode->GetMovable (); movable->SetTransform (newTransform); movable->UpdateMove (); continue; } // if this bone is inside the ragdoll chain if (bones.Contains (parentBoneID)) { Bone nullBone; csOrthoTransform parentTransform = bones.Get (parentBoneID, nullBone) .rigidBody->GetTransform (); csReversibleTransform relativeTransform = bodyTransform * parentTransform.GetInverse (); state->SetBoneUsed (bone.boneID); state->GetVector (bone.boneID) = relativeTransform.GetOrigin (); csQuaternion quaternion; quaternion.SetMatrix (relativeTransform.GetT2O ()); state->GetQuaternion (bone.boneID) = quaternion; continue; } // else this bone is the root of the ragdoll chain, but not of the skeleton else { // TODO: use kinematic object if not the root of the animesh } } }
void reMeshRenderable::updateShader( reShader* shader ) { if (mesh()->hasSkin) { if (!bonesMatched) matchBones(); reMat4 bones[32]; for ( size_t i=0; i<boneLinks.size(); i++) { if (boneLinks[i].bone) { reMat4 boneTransform(boneLinks[i].bone->worldTransform().matrix); reMat4 linkTransform(boneLinks[i].linkMatrix); bones[i] = boneTransform * linkTransform; } } shader->setUniformMatrix(reShader::boneMatrices, 32, glm::value_ptr(bones[0])); } }
bool RagdollAnimNode::CreateRigidBodyNode (iBodyChainNode* node, iRigidBody* parentBody) { iBodyBone* bodyBone = node->GetBodyBone (); // check availability of collider if (!bodyBone->GetBoneColliderCount ()) { factory->manager->Report (CS_REPORTER_SEVERITY_ERROR, "No colliders for bone %i while creating ragdoll chain.\n", bodyBone->GetAnimeshBone ()); return false; } // check availability of joint if (parentBody && !bodyBone->GetBoneJoint ()) { factory->manager->Report (CS_REPORTER_SEVERITY_ERROR, "No joint for bone %i while creating ragdoll chain.\n", bodyBone->GetAnimeshBone ()); return false; } // create bone reference Bone bone; bone.boneID = bodyBone->GetAnimeshBone (); // create rigid body csRef<iRigidBody> rigidBody = factory->dynSys->CreateBody (); bone.rigidBody = rigidBody; // set body position csQuaternion rotation; csVector3 offset; skeleton->GetTransformAbsSpace (bone.boneID, rotation, offset); // TODO: we shouldn't have to use the conjugate of the quaternion, isn't it? csOrthoTransform boneTransform (csMatrix3 (rotation.GetConjugate ()), offset); csOrthoTransform animeshTransform = sceneNode->GetMovable ()->GetTransform (); csOrthoTransform bodyTransform = boneTransform * animeshTransform; rigidBody->SetTransform (bodyTransform); // set body properties if they are defined // (with the Bullet plugin, it is more efficient to define it before the colliders) iBodyBoneProperties* properties = bodyBone->GetBoneProperties (); if (properties) rigidBody->SetProperties (properties->GetMass (), properties->GetCenter (), properties->GetInertia ()); // attach bone colliders for (uint index = 0; index < bodyBone->GetBoneColliderCount (); index++) { iBodyBoneCollider* collider = bodyBone->GetBoneCollider (index); switch (collider->GetGeometryType ()) { case BOX_COLLIDER_GEOMETRY: { csVector3 boxSize; collider->GetBoxGeometry (boxSize); rigidBody->AttachColliderBox (boxSize, collider->GetTransform (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case CYLINDER_COLLIDER_GEOMETRY: { float length, radius; collider->GetCylinderGeometry (length, radius); rigidBody->AttachColliderCylinder (length, radius, collider->GetTransform (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case CAPSULE_COLLIDER_GEOMETRY: { float length, radius; collider->GetCapsuleGeometry (length, radius); rigidBody->AttachColliderCapsule (length, radius, collider->GetTransform (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case CONVEXMESH_COLLIDER_GEOMETRY: { iMeshWrapper* mesh; collider->GetConvexMeshGeometry (mesh); rigidBody->AttachColliderConvexMesh (mesh, collider->GetTransform (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case TRIMESH_COLLIDER_GEOMETRY: { iMeshWrapper* mesh; collider->GetMeshGeometry (mesh); rigidBody->AttachColliderMesh (mesh, collider->GetTransform (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case PLANE_COLLIDER_GEOMETRY: { csPlane3 plane; collider->GetPlaneGeometry (plane); // TODO: add transform rigidBody->AttachColliderPlane (plane, collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } case SPHERE_COLLIDER_GEOMETRY: { csSphere sphere; collider->GetSphereGeometry (sphere); rigidBody->AttachColliderSphere (sphere.GetRadius (), sphere.GetCenter () + collider->GetTransform ().GetOrigin (), collider->GetFriction (), collider->GetDensity (), collider->GetElasticity (), collider->GetSoftness ()); break; } default: factory->manager->Report (CS_REPORTER_SEVERITY_ERROR, "No geometry for collider in bone %i while creating ragdoll chain.\n", bodyBone->GetAnimeshBone ()); return false; } } // TODO: remove bodies if problem // create dynamic joint if (parentBody) bone.joint = CreateDynamicJoint (bodyBone->GetBoneJoint (), parentBody, rigidBody); // store bone bones.Put (bone.boneID, bone); // create child nodes for (uint i = 0; i < node->GetChildCount (); i++) if (!CreateRigidBodyNode (node->GetChild (i), rigidBody)) { factory->manager->Report (CS_REPORTER_SEVERITY_ERROR, "Problem creating ragdoll body for bone %i\n", bodyBone->GetAnimeshBone ()); return false; } return true; }
void IKPhysicalNode::AddConstraint (CS::Animation::EffectorID effectorID, ConstraintData& constraint) { // Find the effector data EffectorData* effector = factory->effectors[effectorID]; // Check if this chain has already some constraints ChainData chainData; if (!chains.Contains (effector->chain)) { // Create a new entry for the chain chainData.previousState = ragdollNode->GetBodyChainState (effector->chain); chainData.constraintCount = 1; chains.Put (effector->chain, chainData); // Set the chain as dynamic ragdollNode->SetBodyChainState (effector->chain, CS::Animation::STATE_DYNAMIC); } else { chainData = chains.Get (effector->chain, chainData); chainData.constraintCount++; } // Compute the world transform of the effector csQuaternion boneRotation; csVector3 boneOffset; skeleton->GetTransformAbsSpace (effector->bone, boneRotation, boneOffset); csOrthoTransform boneTransform (csMatrix3 (boneRotation.GetConjugate ()), boneOffset); csOrthoTransform effectorTransform = effector->transform * boneTransform * sceneNode->GetMovable ()->GetFullTransform (); // Compute the world transform of the constraint target csOrthoTransform targetTransform; switch (constraint.type) { case CONSTRAINT_FIXED: targetTransform = constraint.offset; break; case CONSTRAINT_MOVABLE: targetTransform = constraint.offset * constraint.movable->GetFullTransform (); break; case CONSTRAINT_CAMERA: targetTransform = constraint.offset * constraint.camera->GetTransform (); break; default: break; } // Create a pivot joint constraint.dragJoint = bulletDynamicSystem->CreatePivotJoint (); constraint.dragJoint->Attach (ragdollNode->GetBoneRigidBody (effector->bone), effectorTransform.GetOrigin ()); constraint.dragJoint->SetPosition (targetTransform.GetOrigin ()); constraints.PutUnique (effectorID, constraint); }