void CalBone::calculateState() { // check if the bone was not touched by any active animation if(m_accumulatedWeight == 0.0f) { // set the bone to the initial skeleton state m_translation = m_pCoreBone->getTranslation(); m_rotation = m_pCoreBone->getRotation(); } // get parent bone id int parentId; parentId = m_pCoreBone->getParentId(); if(parentId == -1) { // no parent, this means absolute state == relative state m_translationAbsolute = m_translation; m_rotationAbsolute = m_rotation; } else { // get the parent bone CalBone *pParent; pParent = m_pSkeleton->getBone(parentId); // transform relative state with the absolute state of the parent m_translationAbsolute = m_translation; m_translationAbsolute *= pParent->getRotationAbsolute(); m_translationAbsolute += pParent->getTranslationAbsolute(); m_rotationAbsolute = m_rotation; m_rotationAbsolute *= pParent->getRotationAbsolute(); } // calculate the bone space transformation m_translationBoneSpace = m_pCoreBone->getTranslationBoneSpace(); m_translationBoneSpace *= m_rotationAbsolute; m_translationBoneSpace += m_translationAbsolute; m_rotationBoneSpace = m_pCoreBone->getRotationBoneSpace(); m_rotationBoneSpace *= m_rotationAbsolute; // Generate the vertex transform. If I ever add support for bone-scaling // to Cal3D, this step will become significantly more complex. m_transformMatrix = m_rotationBoneSpace; // calculate all child bones std::list<int>::iterator iteratorChildId; for(iteratorChildId = m_pCoreBone->getListChildId().begin(); iteratorChildId != m_pCoreBone->getListChildId().end(); ++iteratorChildId) { m_pSkeleton->getBone(*iteratorChildId)->calculateState(); } }
///////////////////////////////////// // Purpose: get the absolute rotation // of given boneID // Output: pQ set // Return: none ///////////////////////////////////// void IgfxObject::BoneGetRotateAbs(s32 boneID, Quaternion *pQ) { if(m_pCalModel) { CalSkeleton *pSkel = m_pCalModel->getSkeleton(); CalBone *pBone = pSkel->getBone(boneID); CalQuaternion cQuat = pBone->getRotationAbsolute(); pQ->x = cQuat.x; pQ->y = cQuat.y; pQ->z = cQuat.z; pQ->w = cQuat.w; } }
core::matrix4 CCal3DSceneNode::getBoneMatrix( s32 boneId ) const { if ( calModel == 0 ) return core::matrix4(); CalSkeleton* skeleton = calModel->getSkeleton(); CalBone* bone = skeleton->getBone(boneId); CalQuaternion rot = bone->getRotationAbsolute(); CalVector pos = bone->getTranslationAbsolute(); // Note: Swap Y and Z to convert to Irrlicht coordinates core::quaternion quat = core::quaternion( rot.x, rot.y, rot.z, rot.w ); core::vector3df v = core::vector3df( pos.x, pos.y, pos.z ); core::matrix4 mat = quat.getMatrix(); mat.setTranslation(v); return mat; }
void IKCharacter::draw( int bone_id, float scale, bool additional_drawing ) { CalBone* bone = skeleton->getBone( bone_id ); int parent_id = bone->getCoreBone()->getParentId(); if ( parent_id != -1 ) { // current CalBone* parent = skeleton->getBone( parent_id ); glBegin( GL_LINES ); CalVector v = parent->getTranslationAbsolute(); v*=scale; CalVector c = v; glVertex3f( v.x, v.y, v.z ); v = bone->getTranslationAbsolute(); v*=scale; c += v; c /= 2.0f; glVertex3f( v.x, v.y, v.z ); glEnd(); // world glPushAttrib( GL_CURRENT_BIT ); glColor3f( 0.1f, 0.8f, 0.1f ); glBegin( GL_LINES ); v = world_positions[parent_id]; v*=scale; glVertex3f( v.x, v.y, v.z ); v = world_positions[bone_id]; v*=scale; glVertex3f( v.x, v.y, v.z ); glEnd(); glPopAttrib(); if ( additional_drawing ) { glPushAttrib( GL_CURRENT_BIT ); glBegin( GL_LINES ); // core glColor3f( (parent_id==debug_bone)?1.0f:0.3f, 0.3f, 0.5f ); v = parent->getCoreBone()->getTranslationAbsolute(); v*=scale; glVertex3f( v.x, v.y, v.z ); v = bone->getCoreBone()->getTranslationAbsolute(); v*=scale; glVertex3f( v.x, v.y, v.z ); glEnd(); // draw rotation glPushMatrix(); CalVector root = bone->getCoreBone()->getTranslationAbsolute(); glTranslatef( root.x, root.y, root.z ); CalVector rot; rot.set( 0, 0.1f*scale, 0 ); rot *= bone->getCoreBone()->getRotationAbsolute(); ofEnableAlphaBlending(); glColor4f( 0.2f, 0.2f, 0.8f, 0.2f ); glBegin( GL_TRIANGLES ); //glVertex3f( 0,0,0 ); glVertex3f( rot.x, rot.y, rot.z ); rot *= debug_cached_rotations[bone_id]; glVertex3f( rot.x, rot.y, rot.z ); glEnd(); glColor4f( 0.2f, 0.2f, 0.8f, 0.8f ); rot.set( 0, 0.1f*scale, 0 ); rot *= bone->getCoreBone()->getRotationAbsolute(); glBegin( GL_LINES ); glVertex3f( 0,0,0 ); glVertex3f( rot.x, rot.y, rot.z ); rot *= debug_cached_rotations[bone_id]; glVertex3f( 0,0,0 ); glVertex3f( rot.x, rot.y, rot.z ); glEnd(); ofDisableAlphaBlending(); glPopMatrix(); CalVector u( 0, 0.1f*scale, 0); u *= bone->getRotationAbsolute(); CalVector r( 0.1f*scale, 0, 0 ); r *= bone->getRotationAbsolute(); CalVector f( 0, 0, 0.1f*scale ); f *= bone->getRotationAbsolute(); // right blue glPushMatrix(); root = bone->getTranslationAbsolute(); glTranslatef( root.x, root.y, root.z ); glBegin( GL_LINES ); glColor3f( 0, 0, 1 ); glVertex3f( 0,0,0 ); glVertex3f( r.x, r.y, r.z ); // up red glColor3f( 1, 0, 0 ); glVertex3f( 0,0,0 ); glVertex3f( u.x, u.y, u.z ); // forward green glColor3f( 0, 1, 0 ); glVertex3f( 0,0,0 ); glVertex3f( f.x, f.y, f.z ); glEnd(); glPopMatrix(); // right blue glPushMatrix(); root = world_positions[bone_id]; glTranslatef( root.x, root.y, root.z ); glBegin( GL_LINES ); glColor3f( 0, 0, 1 ); glVertex3f( 0,0,0 ); glVertex3f( r.x, r.y, r.z ); // up red glColor3f( 1, 0, 0 ); glVertex3f( 0,0,0 ); glVertex3f( u.x, u.y, u.z ); // forward green glColor3f( 0, 1, 0 ); glVertex3f( 0,0,0 ); glVertex3f( f.x, f.y, f.z ); glEnd(); glPopMatrix(); glPopAttrib(); } } list<int> children = bone->getCoreBone()->getListChildId(); for ( list<int>::iterator it = children.begin(); it != children.end(); ++it ) { draw( *it, scale, additional_drawing ); } }