Vector3d CSkeleton::fitToLocation(Joint_handle hJoint, Vector3d target_loc) { Joint_handle hRoot = rootOf(hJoint); updateGlobalPostures(hRoot); if(hRoot == parents[hJoint]) { joints[hJoint].setOffset(target_loc); updateGlobalPostures(hRoot); return globals[hJoint].getOffset(); } //updateGlobalPostures(0); Joint_handle hParent = parents[hJoint]; Vector3d dJoint, dTarget; Vector3d pJoint, pParent; pJoint = getGlobalPosition(hJoint); pParent = getGlobalPosition(hParent); dJoint = (pJoint - pParent).Normalize(); dTarget = (target_loc - pParent).Normalize(); Quaterniond qParent = getGlobalRotation(hParent); // dJoint = cast_to_vector(!qParent*dJoint*qParent); // dTarget = cast_to_vector(!qParent*dTarget*qParent); Vector3d axis = Vector3d::Cross(dJoint, dTarget); double dot = Vector3d::Dot(dJoint, dTarget); double angle = acos(Vector3d::Dot(dJoint, dTarget)); Quaterniond qtemp = !qParent*Quaterniond(0, axis.X(), axis.Y(), axis.Z())*qParent; axis = Vector3d(qtemp.X(), qtemp.Y(), qtemp.Z()); Quaterniond rot; rot.FromAxisAngle(angle, axis.X(), axis.Y(), axis.Z()); qtemp = rot*Quaterniond(0, dJoint.X(), dJoint.Y(), dJoint.Z())*!rot; Vector3d pos(qtemp.X(), qtemp.Y(), qtemp.Z()); Vector3d err = pos - dTarget; if( angle == 0.f || (axis.X() == 0 && axis.Y() == 0 && axis.Z() ==0) || dJoint == dTarget) return globals[hJoint].getOffset(); joints[hParent].Rotate(rot); //rotateJoint(hParent, rot); updateGlobalPostures(hParent); //updateGlobalPostures(0); return globals[hJoint].getOffset(); }
void CSkeleton::updateGlobalPostures(Joint_handle hJoint) { if(isRoot(hJoint)) globals[hJoint] = joints[hJoint]; else { size_t parent_idx = parents[hJoint]; globals[hJoint].setOffset(globals[parent_idx].getOffset()); Quaterniond q = globals[parent_idx].getRotation(); Vector3d offset = joints[hJoint].getOffset(); Quaterniond qtemp = q*Quaterniond(0, offset.X(), offset.Y(), offset.Z())*!q; Vector3d pos(qtemp.X(), qtemp.Y(), qtemp.Z()); globals[hJoint].Translate(pos); globals[hJoint].setRotation(q*joints[hJoint].getRotation()); } Joint_handle_iterator jh_it, jh_end = children[hJoint].end(); for(jh_it = children[hJoint].begin(); jh_it != jh_end; ++jh_it) { updateGlobalPostures(*jh_it); } }