void CharacterSkeleton::updateBones() { if (animations.size() > 0) { /*Animation& anim = animations.begin()->second; float timeInTicks = timeInSeconds * anim.getTicksPerSecond(); float animationTime = fmod(timeInTicks, anim.getDuration());*/ updateBoneTransforms(boneHierarchy, rootTransform); } }
void IkSolver::iterateIk() { if (ikChain.size() == 0) buildChain(*rootBone, *effectorBone, ikChain); // perform basic CCD stepIk(); // need the bone transforms to be valid again afterwards for consistency updateBoneTransforms(); }
void IkSolver::solveIk(int maxIterations, double threshold) { if (ikChain.size() == 0) buildChain(*rootBone, *effectorBone, ikChain); for (int i = 0; i < maxIterations; ++i) { // perform basic CCD stepIk(); // need the bone transforms to be valid again afterwards for consistency updateBoneTransforms(); vec3d delta = getEffectorPos() - getTargetPos(); if (abs(dot(delta,delta)) < threshold*threshold) break; } }
void IkSolver::updateBoneTransforms(const Bone *parent, const Bone &b, const mat4d &base) const { const BoneState &bs = boneStates[b.id]; if (parent == 0) bs.boneToWorld = base * mat4d(bs.rot); else { const Bone::Connection &c = *b.findJointWith(*parent); bs.boneToWorld = base * mat4d(bs.rot) * vmath::translation_matrix(-c.pos); } for (int i = 0; i < (int)b.joints.size(); ++i) { const Bone::Connection &c = b.joints[i]; Bone &bn = *c.to; if (&bn != parent) updateBoneTransforms(&b, bn, bs.boneToWorld * vmath::translation_matrix(c.pos)); } }
void IkSolver::setRootBone(const Bone &bone) { // early out if we're not changing anything if (rootBone == &bone) return; // clear the existing IK chain ikChain.clear(); // form a chain between the old root and the new root std::vector<const Bone*> chain; buildChain(bone, *rootBone, chain); // rebuild the rotation values along the chain // this is required because the rotation values are specified relative to the parent bone, // and the parent bone is dependent on which bone is root std::vector<const Bone*>::const_iterator it = chain.begin(); while (it != chain.end()) { const Bone &b = **it; BoneState &bs = boneStates[b.id]; ++it; if (it != chain.end()) { const Bone &nb = **it; BoneState &nbs = boneStates[nb.id]; bs.rot = transpose(nbs.rot); } else bs.rot = minor(bs.boneToWorld); } // set the new root, and its correct position rootBone = &bone; rootPos = boneStates[bone.id].boneToWorld.translation(); updateBoneTransforms(); }
void IkSolver::updateBoneTransforms() const { assert(rootBone != 0); updateBoneTransforms(0, *rootBone, vmath::translation_matrix(rootPos)); }
void IkSolver::applyAllConstraints() { applyAllConstraints(0, *rootBone); updateBoneTransforms(); }
void CharacterSkeleton::updateBoneTransforms(Bone3D* bone, const glm::mat4& parentTransform) { string boneName = bone->boneName; /*if (bRagdoll) { nodeTransformation = bone->nodeTransformation; }*/ //else { if (!bRagdoll && !blendComponents.empty()) { // assuming all bones have animations // TODO: fix for leaf bones that are added by blender with fbx-export "Add Leaf Bones"-option Animation& firstAnimation = animations[blendComponents[0].animationName]; glm::vec3 scaling(0, 0, 0); glm::quat rotation = firstAnimation.interpolateRotation(blendComponents[0].animationStatus * firstAnimation.getDuration(), boneName); glm::vec3 translation(0, 0, 0); float weightAcc = blendComponents[0].weight; for (unsigned int i = 0; i < blendComponents.size(); ++i) { Animation& anim = animations[blendComponents[i].animationName]; float cAnimationTime = blendComponents[i].animationStatus * anim.getDuration(); scaling += anim.interpolateScaling(cAnimationTime, boneName) * blendComponents[i].weight; if (i != 0) { glm::quat cRotation = anim.interpolateRotation(cAnimationTime, boneName); rotation = glm::slerp(rotation, cRotation, 1.0f - weightAcc / (weightAcc + blendComponents[i].weight)); weightAcc += blendComponents[i].weight; } translation += anim.interpolatePosition(cAnimationTime, boneName) * blendComponents[i].weight; } bone->scaling = scaling; glm::mat4 scalingM = glm::scale(glm::mat4(), bone->scaling); bone->rotation = rotation; glm::mat4 rotationM = glm::mat4_cast(bone->rotation); bone->translation = translation; glm::mat4 translationM = glm::translate(glm::mat4(), bone->translation); bone->nodeTransformation = translationM * rotationM * scalingM; } /*else { // TODO: remove else-case float animationTime = 0; Animation& anim = animations.begin()->second; //Animation& anim = animations["AnimStack::metarig|Run"]; if (anim.hasBoneAnimation(boneName)) { bone->scaling = anim.interpolateScaling(animationTime, boneName); glm::mat4 scalingM = glm::scale(glm::mat4(), bone->scaling); //aiQuaternion rotation; //calcInterpolatedRotation(rotation, animationTime, nodeAnim); //aiMatrix3x3 rotationMTmp = (rotation.GetMatrix()); //glm::mat3 rotationTmp = glm::transpose(glm::make_mat3(&rotationMTmp.a1)); //glm::mat4 rotationM = glm::mat4(); //rotationM[0][0] = rotationTmp[0][0]; //rotationM[0][1] = rotationTmp[0][1]; //rotationM[0][2] = rotationTmp[0][2]; //rotationM[1][0] = rotationTmp[1][0]; //rotationM[1][1] = rotationTmp[1][1]; //rotationM[1][2] = rotationTmp[1][2]; //rotationM[2][0] = rotationTmp[2][0]; //rotationM[2][1] = rotationTmp[2][1]; //rotationM[2][2] = rotationTmp[2][2]; bone->rotation = anim.interpolateRotation(animationTime, boneName); glm::mat4 rotationM = glm::mat4_cast(bone->rotation); bone->translation = anim.interpolatePosition(animationTime, boneName); glm::mat4 translationM = glm::translate(glm::mat4(), bone->translation); nodeTransformation = translationM * rotationM * scalingM; } else nodeTransformation = bone->nodeTransformation; } bone->nodeTransformation = nodeTransformation; }*/ //glm::mat4 globalTransformation = parentTransform * bone->nodeTransformation; if (bRagdoll && bone->bHasRigidBody) { btTransform transform = bone->rigidBody->getCenterOfMassTransform(); glm::mat4 rigidBodyTransform; transform.getOpenGLMatrix(glm::value_ptr(rigidBodyTransform)); bone->globalTransformation = glm::translate(rigidBodyTransform, -bone->rigidBodyOffset); } else bone->globalTransformation = parentTransform * bone->nodeTransformation; bone->finalTransformation = bone->globalTransformation * bone->boneOffset; for (auto& it : bone->children) updateBoneTransforms(it, bone->globalTransformation); }