int CalSkeleton::getBoneLinesStatic(float *pLines) { int nrLines; nrLines = 0; rde::vector<CalBone *>::iterator iteratorBone; for(iteratorBone = m_vectorBone.begin(); iteratorBone != m_vectorBone.end(); ++iteratorBone) { int parentId; parentId = (*iteratorBone)->getCoreBone()->getParentId(); if(parentId != -1) { CalBone *pParent; pParent = m_vectorBone[parentId]; const CalVector& translation = (*iteratorBone)->getCoreBone()->getTranslationAbsolute(); const CalVector& translationParent = pParent->getCoreBone()->getTranslationAbsolute(); *pLines++ = translationParent[0]; *pLines++ = translationParent[1]; *pLines++ = translationParent[2]; *pLines++ = translation[0]; *pLines++ = translation[1]; *pLines++ = translation[2]; nrLines++; } } return nrLines; }
void CalMixer::applyBoneAdjustments() { CalSkeleton * pSkeleton = m_pModel->getSkeleton(); std::vector<CalBone *>& vectorBone = pSkeleton->getVectorBone(); unsigned int i; for( i = 0; i < m_numBoneAdjustments; i++ ) { CalMixerBoneAdjustmentAndBoneId * ba = & m_boneAdjustmentAndBoneIdArray[ i ]; CalBone * bo = vectorBone[ ba->boneId_ ]; CalCoreBone * cbo = bo->getCoreBone(); if( ba->boneAdjustment_.flags_ & CalMixerBoneAdjustmentFlagMeshScale ) { bo->setMeshScaleAbsolute( ba->boneAdjustment_.meshScaleAbsolute_ ); } if( ba->boneAdjustment_.flags_ & CalMixerBoneAdjustmentFlagPosRot ) { const CalVector & localPos = cbo->getTranslation(); CalVector adjustedLocalPos = localPos; CalQuaternion adjustedLocalOri = ba->boneAdjustment_.localOri_; static float const scale = 1.0f; float rampValue = ba->boneAdjustment_.rampValue_; static bool const replace = true; static float const unrampedWeight = 1.0f; bo->blendState( unrampedWeight, adjustedLocalPos, adjustedLocalOri, scale, replace, rampValue ); } } }
void IKCharacter::pullWorldPositions( int root_id, int leaf_id ) { CalVector root_pos; if ( auto_root_follow ) { // get root pos int skel_root_id = skeleton->getCoreSkeleton()->getVectorRootCoreBoneId()[0]; root_pos = skeleton->getBone(skel_root_id)->getTranslationAbsolute(); } // work from the leaves down to the root deque<int> queue; if ( leaf_id == -1 ) queue.insert( queue.begin(), leaf_bones.begin(), leaf_bones.end() ); else queue.push_back( leaf_id ); while ( !queue.empty() ) { int id = queue.front(); queue.pop_front(); CalBone* bone = skeleton->getBone(id); world_positions[id] = bone->getTranslationAbsolute() - root_pos; int parent_id = bone->getCoreBone()->getParentId(); if ( parent_id != -1 && id != root_id ) queue.push_back( parent_id ); } }
const std::list<int>& BoneBridgeCAL3D::GetListChildBoneID() const { CalBone* calBone = (CalBone*)GetCalBone(); CalCoreBone* coreBone = calBone->getCoreBone(); std::list<int>& listChildID = coreBone->getListChildId(); return listChildID; }
void IKCharacter::pullWorldPositions( int root_id, int leaf_id ) { deque<int> queue; if ( leaf_id == -1 ) queue.insert( queue.begin(), leaf_bones.begin(), leaf_bones.end() ); else queue.push_back( leaf_id ); // work backwards up the tree while ( !queue.empty() ) { int id = queue.front(); queue.pop_front(); CalBone* bone = skeleton->getBone(id); world_positions[id] = bone->getTranslationAbsolute(); int parent_id = bone->getCoreBone()->getParentId(); if ( parent_id != -1 && id != root_id ) queue.push_back( parent_id ); } }
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 ); } }
void IKCharacter::solve( int iterations, int root_id, int leaf_id ) { while ( iterations>0 ) { // start at leaf nodes deque<int> queue; // push leaf bones to target positions for ( int i=0; i<leaf_bones.size(); i++ ) { // if we have a leaf id to use, skip all other leaves if ( leaf_id != -1 && leaf_id != leaf_bones[i] ) continue; // if we have a target for this one if ( leaf_targets.find(leaf_bones[i]) != leaf_targets.end() ) { // set it world_positions[leaf_bones[i]] = leaf_targets[leaf_bones[i]].second; } int parent_id = skeleton->getCoreSkeleton()->getCoreBone( leaf_bones[i] )->getParentId(); if ( parent_id != -1 ) queue.push_back( parent_id ); } // queue to handle branching deque< int > branch_queue; while ( !queue.empty() || !branch_queue.empty() ) { // if main queue is empty then we are ready to deal with branches if ( queue.empty() ) { queue.push_back( branch_queue.front() ); branch_queue.pop_front(); continue; } int next_id = queue.front(); queue.pop_front(); // bail out if we should if ( root_id != -1 && next_id == root_id ) continue; CalBone* bone = skeleton->getBone( next_id ); list<int>& children = bone->getCoreBone()->getListChildId(); // is this a branch? if ( children.size()>1 ) { // still other children to process -- push to branch queue if ( !queue.empty() ) { branch_queue.push_back( next_id ); continue; } // otherwise, process branch here // if we're here, then all the children of this branch have been processed already int parent_id = bone->getCoreBone()->getParentId(); if ( parent_id != -1 ) { //printf("averaging %lu positions for %s wc %f: ", children.size(), bone->getCoreBone()->getName().c_str(), getWeightCentre( next_id ) ); // fetch all child positions vector<CalVector> results; results.insert( results.begin(), children.size(), world_positions[next_id] ); int count=0; for ( list<int>::iterator it = children.begin(); it != children.end(); ++it,++count ) { // child_pos CalVector& b_c = world_positions[*it]; // current pos CalVector& b_p = results[count]; // now, the bone is the wrong length. correct its length to fulfil size constraint. CalVector delta = b_c - b_p; float length = delta.length(); length = max( 0.00001f, length ); // pointing from parent to child CalVector direction = delta/length; CalCoreBone* child_bone = skeleton->getCoreSkeleton()->getCoreBone( *it ); CalVector rest_delta = bone->getCoreBone()->getTranslationAbsolute() - child_bone->getTranslationAbsolute(); float desired_length = rest_delta.length(); float delta_length = desired_length - length; // balance according to weight_centre float weight_centre = getWeightCentre(next_id); // move b_c += weight_centre * delta_length * direction; b_p -= (1.0f-weight_centre) * delta_length * direction; //printf("%s %f (%f %f %f), ", child_bone->getName().c_str(), delta_length, b_p.x, b_p.y, b_p.z ); } //printf("\n"); // now average CalVector average; for ( int i=0; i<results.size(); i++ ) { average += results[i]; } average /= results.size(); // store world_positions[next_id] = average; // add parent queue.push_back( parent_id ); } } else { // children.size() is exactly 1 assert( children.size()==1 ); int child_id = children.front(); // child_pos CalVector& b_c = world_positions[child_id]; // current pos CalVector& b_p = world_positions[next_id]; // now, the bone is the wrong length. correct its length to fulfil size constraint. float desired_length = getBoneLength(next_id); CalVector delta = b_c - b_p; float length = delta.length(); length = max( 0.00001f, length ); length = min( desired_length*1.5f, length ); // pointing from parent to child CalVector direction = delta/length; float delta_length = desired_length - length; // balance according to weight_centre float weight_centre = getWeightCentre(next_id); // move b_c += weight_centre * delta_length * direction; b_p -= (1.0f-weight_centre) * delta_length * direction; // add parent int parent_id = bone->getCoreBone()->getParentId(); if ( parent_id != -1 ) queue.push_back( parent_id ); } } iterations--; } }