void Skeleton::update( const float &time, bool updateAnim) { if( updateAnim ) { // update all bones local values (rotation fcurves) int c = 0; for(int i=0; i<m_bones.size(); ++i ) { //float rx = getBone(i)->localEulerRotation.x; //float ry = getBone(i)->localEulerRotation.y; //float rz = getBone(i)->localEulerRotation.z; //if( ((FCurve*)m_localEulerRotationAnims.m_data[c])->m_numKeys > 0 ) // rx = math::degToRad(((FCurve*)m_localEulerRotationAnims.m_data[c])->eval(time)); //if( ((FCurve*)m_localEulerRotationAnims.m_data[c+1])->m_numKeys > 0 ) // ry = math::degToRad(((FCurve*)m_localEulerRotationAnims.m_data[c+1])->eval(time)); //if( ((FCurve*)m_localEulerRotationAnims.m_data[c+2])->m_numKeys > 0 ) // rz = math::degToRad(((FCurve*)m_localEulerRotationAnims.m_data[c+2])->eval(time)); getBone(i)->localEulerRotation = math::Vec3f( math::degToRad(((FCurve*)m_localEulerRotationAnims.m_data[c])->eval(time)), math::degToRad(((FCurve *)m_localEulerRotationAnims.m_data[c+1])->eval(time)), math::degToRad(((FCurve*)m_localEulerRotationAnims.m_data[c+2])->eval(time)) ); //getBone(i)->localEulerRotation = math::Vec3f( rx, ry, rz ); c+=3; } } // update global transforms (depends on hierarchy) //updateBone(time, m_root, math::Matrix44f::Identity(), 0.0f); updateBone(time, m_root, math::Matrix44f::ScaleMatrix(0.1f,0.1f,0.1f), 0.0f); // update uniform which goes via geometry into the shader for( int j=0; j<m_bones.size(); ++j ) m_boneMatricesUniform->setElement( j, &getBone(j)->vertexTransform ); }
BoneNode* Skeleton::createBone( char const* name , char const* parentName ) { if ( !parentName ) parentName = CF_BASE_BONE_NAME; BoneNode* parent = getBone( parentName ); return createBone( name , parent->id ); }
void Skeleton::addAnimationTrackGroup(animation::AnimationTrackGroup*group){ animation::TransAnimationGroup* tgroup=dynamic_cast<animation::TransAnimationGroup*>(group); if(!tgroup) return; animation::AnimationController*c=m_animationMixer->addTrackGroup(tgroup); //connect tracks to bones animation::IAnimationTrackList::const_iterator p=group->getTracks().begin(); animation::IAnimationTrackList::const_iterator end=group->getTracks().end(); for(;p!=end;++p) { animation::IAnimationTrack* t=*p; animation::TransformationAnimationTrack* tt= dynamic_cast<animation::TransformationAnimationTrack*>(t); if(tt) { BoneNode* b=getBone(t->getName()); if(b){ tt->setAffectedNodeID(b->getID()); //tt->SetNode(b); b->AttachAnimationTrack(tt,c); } } } group->refreshAffectIDMap(); }
/* This function sets sibling or child for parent bone If parent bone does not have a child, then pChild is set as parent's child else pChild is set as a sibling of parents already existing child */ int CMUSkeleton::setChildrenAndSibling(int parent, Bone *pChild) { Bone *pParent; //Get pointer to root bone pParent = getBone(m_pRootBone, parent); if(pParent==NULL) { printf("inbord bone is undefined\n"); return(0); } else { //if pParent bone does not have a child //set pChild as parent bone child if(pParent->child == NULL) { pParent->child = pChild; } else { //if pParent bone already has a child //set pChils as pParent bone's child sibling pParent=pParent->child; while(pParent->sibling != NULL) pParent = pParent->sibling; pParent->sibling = pChild; } return(1); } }
// attach a gameobject inplace to a specified bone void gkSkeleton::attachObjectToBoneInPlace(gkString boneName,gkGameObject* gobj) { gkBone* bone = getBone(boneName); if (bone) { if (m_controller) gobj->setParentInPlace(m_controller); else gobj->setParentInPlace(this); bone->attachObject(gobj); gkMatrix4 objMat = gobj->getTransform(); // get the current transformation of this bone gkMatrix4 boneMat = bone->getTransform(); gkMatrix4 objInBoneSpace = boneMat.inverse() * objMat ; gkTransformState* ts = new gkTransformState(objInBoneSpace); gobj->_setBoneTransform(ts); } else { gkLogger::write("unknown bone-name:"+boneName+" to attach "+gobj->getName()+" to "+getName(),true); } }
/* This recursive function traverces skeleton hierarchy and returns a pointer to the bone with index - bIndex ptr should be a pointer to the root node when this function first called */ Bone* CMUSkeleton::getBone(Bone *ptr, int bIndex) { static Bone *theptr; if(ptr==NULL) return(NULL); else if(ptr->idx == bIndex) { theptr=ptr; return(theptr); } else { getBone(ptr->child, bIndex); getBone(ptr->sibling, bIndex); return(theptr); } }
void HelloWorld::onFrameEvent( cocos2d::extension::CCBone* bone, const char* evt, int originFrameIndex, int currentFrameIndex ) { if (originFrameIndex == currentFrameIndex) { CCPoint p = m_pArmature->getBone("Layer2")->getDisplayRenderNode()->convertToWorldSpaceAR( ccp (0, 0)); CCLOG("%s", evt); m_pArmature->getAnimation()->pause(); } }
//-------------------------------------------------------------- void ofxFBXSkeleton::enableExternalControlRecursive( ofxFBXBone* aBone ) { if( aBone == NULL ) return; map<string, ofxFBXBone* >::iterator it; for(it = sourceBones.begin(); it != sourceBones.end(); ++it ) { if( it->second->fbxNode->GetParent() == aBone->fbxNode ) { // it->second->enableExternalControl(); getBone( it->first )->enableExternalControl(); enableExternalControlRecursive( it->second ); } } }
//-------------------------------------------------------------- void ofxFBXSkeleton::enableExternalControl( string aName ) { // loop through hierarchy to make children also controlled externally ofxFBXBone* bone = getBone( aName ); if(bone == NULL) { ofLogWarning("ofxFBXSkeleton :: enableExternalControl : can not find bone with name ") << aName; return; } bone->enableExternalControl(); enableExternalControlRecursive( getSourceBone(aName) ); }
void Armature::removeBoneByName(std::string boneName){ if((boneName == "") || (boneName == " ")) { return; } Bone* bone = getBone(boneName); if(bone) { removeBone(bone); } }
MOBone * MArmature::getBoneByName(const char * name) { M_PROFILE_SCOPE(MArmature::getBoneByName); unsigned int i; for(i=0; i<m_bonesNumber; i++) // scan bones { MOBone * bone = getBone(i); if(strcmp(name, bone->getName()) == 0) return bone; } return NULL; }
void Skeleton::setupBoneWorldTransform( RenderSystem* renderSys , Matrix4 const& baseWorld , Matrix4* boneTrans ) { if ( boneTrans ) { if ( mUseInvLocalTrans ) { for( int i = 0 ; i < getBoneNum(); ++i ) { BoneNode* bone = getBone(i); Matrix4 worldTrans; //World = InvLocal * Bone * BaseWorld TransformUntility::mul( worldTrans , bone->invLocalTrans , boneTrans[i] ); TransformUntility::mul( worldTrans , worldTrans , baseWorld ); renderSys->setWorldMatrix( i , worldTrans ); } } else { for( int i = 0 ; i < getBoneNum(); ++i ) { BoneNode* bone = getBone(i); Matrix4 worldTrans; TransformUntility::mul( worldTrans , boneTrans[i] , baseWorld ); renderSys->setWorldMatrix( i , worldTrans ); } } } else { for( int i = 0 ; i < getBoneNum(); ++i ) { BoneNode* bone = getBone(i); Matrix4 worldTrans; renderSys->setWorldMatrix( i , baseWorld ); } } }
void gkSkeletonResource::copyBones(gkSkeletonResource& other) { { Bones::Iterator biter = other.m_bones.iterator(); while (biter.hasMoreElements()) createBone(biter.getNext().second->getName()); } { Bones::Iterator biter = other.m_bones.iterator(); while (biter.hasMoreElements()) { gkBone* sBone = biter.getNext().second; gkBone* sParent = sBone->getParent(); gkBone* dBone = getBone(sBone->getName()); GK_ASSERT(dBone); if (sParent) { gkBone* dParent = getBone(sParent->getName()); GK_ASSERT(dParent); dBone->setParent(dParent); } dBone->setRestPosition(sBone->getRest()); } } { gkBone::BoneList::Iterator biter = other.m_rootBoneList.iterator(); while (biter.hasMoreElements()) { gkBone* sBone = biter.getNext(); gkBone* dBone = getBone(sBone->getName()); GK_ASSERT(dBone); m_rootBoneList.push_back(dBone); } } }
void Armature::addDBObject(DBObject* object){ if(checkIfClass<Slot>(object)) { Slot* slot = (Slot*)object; if(!getSlot(slot->name)) { _slotList.push_back(slot); } } else if(checkIfClass<Bone>(object)) { Bone* bone = (Bone*) object; if(!getBone(bone->name)) { _boneList.push_back(bone); sortBoneList(); } } }
// attach a gameobject to the specified bone with optional transformation void gkSkeleton::attachObjectToBone(gkString boneName,gkGameObject* gobj,gkTransformState* transform) { gkBone* bone = getBone(boneName); if (bone) { // if there is an entity add the attached object there otherwise on the skeleton itself if (m_controller) m_controller->addChild(gobj); else addChild(gobj); bone->attachObject(gobj); if (transform) gobj->_setBoneTransform(transform); } else { gkLogger::write("unknown bone-name:"+boneName+" to attach "+gobj->getName()+" to "+getName(),true); } }
DBBone* DBArmature::createBone(BoneData* boneData) { std::string boneName = boneData->name; DBBone *existedBone = getBone(boneName); if(existedBone != nullptr) return existedBone; std::string parentName = boneData->parent; DBBone *bone = nullptr; if( !parentName.empty() && !this->getBone(parentName)) { BoneData* parentBoneData = this->_pArmatureData->getBoneData(parentName); createBone(parentBoneData); } bone = DBBone::create(boneData); addBone(bone, parentName.c_str()); return bone; }
void Armature::addChild(DBObject* object, std::string parentName){ if(!object) { return; } if(parentName != "") { Bone* boneParent = getBone(parentName); if (boneParent) { boneParent->addChild(object); } } else { if(object->parent) { object->parent->removeChild(object); } object->setArmature(this); } }
// 解析出刀塔骨架数据 Dota_Skeleton_Data* DotaAnimParser::parseDotaSkeletonData( const std::string &fcaFile) { const float PI = 3.14159265358979323846f; ByteArray byteArray; bool bRet = byteArray.loadFromZipFile(fcaFile.c_str(), "cha"); if (!bRet) return nullptr; Dota_Skeleton_Data * skeletonData = new Dota_Skeleton_Data(); if (skeletonData == nullptr) { byteArray.close(); return nullptr; } skeletonData->name = readName(byteArray); CCLOG("RoleName:%s\n", skeletonData->name.c_str()); float factor = 0.1f; if (skeletonData->name.substr(0, 14) == "effect/eff_UI_") factor = 0.5f; int boneCount = byteArray.readInt(); CCLOG("BoneCnt:%d\n", boneCount); for (int i = 0; i < boneCount; i++) { Dota_Bone_Data * boneData = new Dota_Bone_Data(); boneData->name = readName(byteArray); boneData->textureName = readName(byteArray); boneData->index = byteArray.readInt(); skeletonData->boneDataList.push_back(boneData); CCLOG("BoneData:\nName:%s\nTextureName:%s\nIndex:%d\n\n", boneData->name.c_str(), boneData->textureName.c_str(), boneData->index); } CCLOG("BoneCnt:%d\n", (int)skeletonData->boneDataList.size()); int animCount = byteArray.readInt(); CCLOG("AnimCnt:%d\n", animCount); for (int i = 0; i < animCount; i++) { Dota_Anim_Data * animData = new Dota_Anim_Data(); animData->name = readName(byteArray); CCLOG("AnimName:%s\n", animData->name.c_str()); byteArray.readBytes(animData->unknownData, sizeof(animData->unknownData)); int frameCount = byteArray.readInt(); CCLOG("FrameCnt:%d\n", frameCount); for (int j = 0; j < frameCount; j++) { Dota_Frame_Data * frameData = new Dota_Frame_Data(); frameData->type = byteArray.readInt(); if (frameData->type == 1) { frameData->unknownData1 = byteArray.readInt(); CCLOG("UnknownData1:%d\n", frameData->unknownData1); frameData->soundName = readName(byteArray); byteArray.readBytes(frameData->soundData, sizeof(frameData->soundData)); frameData->unknownData2 = byteArray.readInt(); CCLOG("UnknownData2:%d\n", frameData->unknownData2); } int slotCount = byteArray.readInt(); for (int k = 0; k < slotCount; k++) { Dota_Slot_Data * slotData = new Dota_Slot_Data(); slotData->boneIndex = byteArray.readShort(); slotData->opacity = byteArray.readByte(); float a = byteArray.readFloat(); float b = byteArray.readFloat(); float c = byteArray.readFloat(); float d = byteArray.readFloat(); float tx = byteArray.readFloat(); float ty = byteArray.readFloat(); slotData->x = tx * factor; slotData->y = ty * factor; slotData->skX = atan2(-c, d) * (180/PI); slotData->skY = atan2(b, a) * (180/PI); slotData->scX = sqrt(a*a + b*b); slotData->scY = sqrt(c*c + d*d); frameData->slotDataList.push_back(slotData); } animData->frameDataList.push_back(frameData); } CCLOG("FrameCnt:%d\n", animData->frameDataList.size()); skeletonData->animDataList.push_back(animData); } byteArray.close(); for (int i = 0; i < (int)skeletonData->animDataList.size(); i++) { Dota_Anim_Data * animData = skeletonData->animDataList[i]; Dota_Anim_Data2 * animData2 = new Dota_Anim_Data2(); for (int j = 0; j < (int)animData->frameDataList.size(); j++) { Dota_Frame_Data * frameData = animData->frameDataList[j]; for (int k = 0; k < (int)frameData->slotDataList.size(); k++) { Dota_Slot_Data * slotData = frameData->slotDataList[k]; if (frameData->type == 1 && 0 == k) slotData->soundName = frameData->soundName; slotData->zOrder = k; //slotData->boneIndex; std::string boneName = getBone(skeletonData->boneDataList, slotData->boneIndex); Dota_Anim_Data2::iterator iter = animData2->find(boneName); if (iter == animData2->end()) { Dota_Timeline_Data * timelineData = new Dota_Timeline_Data(); timelineData->insert(Dota_Timeline_Data::value_type(toString(j), slotData)); animData2->insert(Dota_Anim_Data2::value_type(boneName, timelineData)); skeletonData->firstFrameOfBoneMap.insert(Dota_First_Frame_Data::value_type(boneName, slotData)); } else { Dota_Timeline_Data * timelineData = iter->second; Dota_Timeline_Data::iterator iter2 = timelineData->find(toString(j)); if (iter2 == timelineData->end()) { timelineData->insert(Dota_Timeline_Data::value_type(toString(j), slotData)); } } } } skeletonData->animDataMap.insert(std::map<std::string, Dota_Anim_Data2 *>::value_type(animData->name, animData2)); } return skeletonData; }
void Animator::update() { if (! currentAnimation) { return; } glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glLoadIdentity(); glTranslatef(320.0f, 300.0, 0.0f); glScalef(1.0f / 3.0f, 1.0f / 3.0f, 1.0f); glBindTexture(GL_TEXTURE_2D, texture[0]); currentFrame = currentFrame % currentAnimation->frameCount; AnimationFrame* f = currentAnimation->frames[currentFrame]; AnimationFrame::ElementList::reverse_iterator i = f->elements.rbegin(); int test = 0; for (; i != f->elements.rend(); ++i) { AnimationFrameElement* e = *i; BoneInfo* b = getBone(e->boneID); if (b) { BoneFrameInfo* f = b->infos[e->frameID]; // 遍历顶点范围 glPushMatrix(); // tx ty glTranslatef(e->tx, e->ty, 0); // sx sy float sx = sqrtf(e->a * e->a + e->c * e->c); float sy = sqrtf(e->b * e->b + e->d * e->d); // http://www.infogroupindia.com/blog/posts/589/action-script-3-2d-matrix-scale-and-rotation-extraction // 阿三写的居然对了 // 不过完全没看懂 // 通过tan得到的角度,-pi / 2 ~ pi / 2 float sign = atanf(-e->c / e->a); // 通过cos得到的角度,0 ~ pi float rad = acosf(e->a / sx); // 通过cos跟tan的值才能完全判断出角度 float deg = rad * 180.0f / M_PI; // 修正错误的角度值 if (deg > 90 && sign > 0) { // 应该在第三象限 deg = 360 - deg; } else if (deg < 90 && sign < 0) { // 应该在第四象限 deg = 360 - deg; } // 误差值 0.001 // 蜘蛛女王还是有些问题,很奇怪 if (((deg > 270 && deg < 360) || (deg > 0 && deg < 90)) && e->a < -0.001 || deg > 90 && deg < 270 && e->a > 0.001) { sx *= -1.0f; } if (((deg > 270 && deg < 360) || (deg > 0 && deg < 90)) && e->d < -0.001 || deg > 90 && deg < 270 && e->d > 0.001) { sy *= -1.0f; //log.Write(COLOR_WHITE, "渲染到上下翻转帧元素 部位ID %s 帧ID %d x %f y %f z %f a %f b %f c %f d %f", boneNames[e->boneID].c_str(), e->frameID, e->tx, e->ty, e->tz, e->a, e->b, e->c, e->d); } glScalef(sx, sy, 1.0); glRotatef(deg, 0.0f, 0.0f, 1.0f); int nowIndex = f->vStartIndex; int endIndex = f->vStartIndex + f->vCount; glBegin(GL_POLYGON); for (; nowIndex < endIndex; ++nowIndex) { Vertex* v1 = vertexes[nowIndex]; glTexCoord2f(v1->u, v1->v); glVertex3f(v1->x, v1->y, v1->z); } glEnd(); glPopMatrix(); } } //currentFrame++; //log.Write(COLOR_WHITE, "当前帧数 %d %d", currentFrame, currentAnimation->frameCount); }
Skeleton::Skeleton( unsigned char *skel, unsigned char *_pose, unsigned char *anims ) { //unsigned char *data = testSkel11; int numBones = skel[0]; unsigned char *parentIndices = &skel[1]; float *lengths = (float *)&skel[1+numBones*sizeof(char)]; float *pose = (float *)_pose; unsigned char *rotAnims = anims; for(int i=0; i<numBones; ++i ) { Bone *b = new Bone(); m_bones.push_back( b ); if( i>0 ) { ((Bone*)m_bones.m_data[parentIndices[i]])->childBones.push_back( b ); b->parent = (Bone*)m_bones.m_data[parentIndices[i]]; } b->length = lengths[i]; // apply pose b->localEulerRotation.x = math::degToRad(pose[i]); b->localEulerRotation.y = math::degToRad(pose[numBones+i]); b->localEulerRotation.z = math::degToRad(pose[numBones*2+i]); //printf( "bone %i %f %f %f\n", i, b->localEulerRotation.x, b->localEulerRotation.y, b->localEulerRotation.z ); if( rotAnims ) { // read animations of rotations // the tricky bit: we dont know how much space each anim uses so we // have to find out after loading it FCurve *rotAnimX = new FCurve( rotAnims, pose[i] ); rotAnims += 1 + rotAnimX->m_numKeys*2*sizeof(float); FCurve *rotAnimY = new FCurve( rotAnims, pose[numBones+i] ); rotAnims += 1 + rotAnimY->m_numKeys*2*sizeof(float); FCurve *rotAnimZ = new FCurve( rotAnims, pose[numBones*2+i] ); rotAnims += 1 + rotAnimZ->m_numKeys*2*sizeof(float); m_localEulerRotationAnims.push_back( rotAnimX ); m_localEulerRotationAnims.push_back( rotAnimY ); m_localEulerRotationAnims.push_back( rotAnimZ ); } } m_root = (Bone*)m_bones.m_data[0]; // create the uniform which will be attached to geometry which has to be driven by skin deformation m_boneMatricesUniform = new Attribute( 16 ); // just fill up the list with dummy entries (will be overwritten in update) for( int j=0; j<m_bones.size(); ++j ) m_boneMatricesUniform->appendElement( &math::Matrix44f::Identity() ); // update skeleton in refpose (updates global transform) // TODO: replace with apply pose update( 0.001f, false ); // store refpose transforms for(int i=0; i<numBones; ++i ) { math::Matrix44f bindPoseInv = getBone(i)->globalTransform; bindPoseInv.invert(); getBone(i)->bindPoseInv = bindPoseInv; } }