• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當自強而不息

            Using Key?Framed Skeletal Animation(3)

            Assuming you want more than one animation set loaded at once, you can even create a class that contains an array (or rather, a linked list) of cAnimationSet classes, which means that you can access a whole slew of animations with one interface! This class, called cAnimationCollection, is also derived from the cXParser class, so you can parse .X files directly from the class in which you'll be storing the animations.

            Here's the class declaration for cAnimationCollection:

            class cAnimationCollection : public cXParser
            {
            public:
            DWORD m_NumAnimationSets;
            cAnimationSet *m_AnimationSets;
            protected:
            // Parse an .X file object
            BOOL ParseObject(IDirectXFileData *pDataObj,
            IDirectXFileData *pParentDataObj,
            DWORD Depth,
            void **Data, BOOL Reference);
            public:
            cAnimationCollection();
            ~cAnimationCollection();
            	BOOL Load(char *Filename);
            void Free();
            void Map(D3DXFRAME *RootFrame);
            void Update(char *AnimationSetName, DWORD Time);
            };

            The details of each function in the cAnimationCollection class are not very important at this point so I'll get back to them in a bit. At this point, all you're interested in is reading in that animation data from an .X file. The custom .X parser contained in the cAnimationCollection class does just that, it loads the data from the Animation objects' data into the dizzying array of objects you've just seen.

            For every AnimationSet object you encounter in the .X file being parsed, you need to allocate a cAnimationSet class and add it to the linked list of animation sets already loaded. The most current cAnimationSet object is stored at the start of the linked list, which makes it easy to determine which animation−set data you are currently using.

            From here, you can appropriately parse the Animation objects. If you were to keep the most current cAnimationSet object at the start of your linked list, every following Animation object that you parse would belong to that animation−set object. The same goes for the AnimationKey objects, their data would belong to the first cAnimation object in the linked list.

            I will skip the constructors and destructors for all the different classes because you only need them to clear and release each class's data. You're only interested in a couple functions, the first being cAnimationCollection::ParseObject, which deals with each animation object being parsed from an .X file.

            The ParseObject function starts by checking whether the currently enumerated object is an AnimationSet. If it is, a new cAnimationSet object is allocated and linked to the list of objects, while the animation−set object is simultaneously named for further reference.

            BOOL cAnimationCollection::ParseObject( 
            IDirectXFileData *pDataObj,
            IDirectXFileData *pParentDataObj,
            DWORD Depth,
            void **Data, BOOL Reference)
            {
            const GUID *Type = GetObjectGUID(pDataObj);
            DWORD i;
            	// Check if object is AnimationSet type
            if(*Type == TID_D3DRMAnimationSet) {
            // Create and link in a cAnimationSet object
            cAnimationSet *AnimSet = new cAnimationSet();
            AnimSet−>m_Next = m_AnimationSets;
            m_AnimationSets = AnimSet;
            		// Increase # of animation sets
            m_NumAnimationSets++;
            		// Set animation set name (set a default one if none)
            if(!(AnimSet−>m_Name = GetObjectName(pDataObj)))
            AnimSet−>m_Name = strdup("NoName");
            }

            As you can see, nothing special goes on with the animation set objects, you're merely allocating an object that will eventually hold the upcoming Animation data objects. Speaking of which, you want to parse the Animation objects next.

            // Check if object is Animation type
            if(*Type == TID_D3DRMAnimation && m_AnimationSets) {
            // Add a cAnimation class to top−level cAnimationSet
            cAnimation *Anim = new cAnimation();
            Anim−>m_Next = m_AnimationSets−>m_Animations;
            m_AnimationSets−>m_Animations = Anim;
            	// Increase # of animations
            m_AnimationSets−>m_NumAnimations++;
            }

            Again, nothing special going on there. In the preceding code, you're simply ensuring that there's a cAnimationSet object allocated at the start of the linked list. If there is, you can allocate and link a cAnimation object to the list in the cAnimationSet object.

            While we're on the topic of the cAnimation object, the next bit of code retrieves the name of the frame instance located within the Animation object.

            // Check if a frame reference inside animation object
            if(*Type == TID_D3DRMFrame && Reference == TRUE && m_AnimationSets && m_AnimationSets−>m_Animations) {
            // Make sure parent object is an Animation object
            if(pParentDataObj && *GetObjectGUID(pParentDataObj) == TID_D3DRMAnimation) {
            // Get name of frame and store it as animation
            if(!(m_AnimationSets−>m_Animations−>m_Name = GetObjectName(pDataObj)))
            m_AnimationSets−>m_Animations−>m_Name=strdup("NoName");
            }
            }

            You can see in this code that only referenced frame objects are allowed in the Animation object, a fact that you can verify by checking the parent object's template GUID. Whew! So far this code is pretty easy, isn't it? Well, I don't want to burst your bubble, but the hardest is yet to come! In fact, the most difficult part of loading animation data from an .X file is loading the key data. Don't let me scare you away, though; the key data is nothing more than a time value and an array of values that represent the key data.

            The remaining code in the ParseObject function checks to see which type of key data an AnimationKey object holds. Depending on the type of data, the code branches off and reads the data into the specific key objects (m_RotationKeys, m_TranslationKeys, m_ScaleKeys, and m_MatrixKeys) inside the current cAnimation object. Take a closer look to see how simple this code really is.

            // Check if object is AnimationKey type
            if(*Type == TID_D3DRMAnimationKey && m_AnimationSets && m_AnimationSets−>m_Animations) {
            // Get a pointer to top−level animation object
            cAnimation *Anim = m_AnimationSets−>m_Animations;
            	// Get a data pointer
            DWORD *DataPtr = (DWORD*)GetObjectData(pDataObj, NULL);
            	// Get key type
            DWORD Type = *DataPtr++;
            	// Get # of keys to follow
            DWORD NumKeys = *DataPtr++;

            In addition to checking to see whether there are valid cAnimationSet and cAnimation objects at the start of the linked list of objects, the preceding code gets a pointer to the key data and pulls out the key type value and the number of keys to follow. Using the key type, the code then branches off to allocate the key−frame objects and load in the key data.

            // Branch based on key type
            switch(Type) {
            case 0: // Rotation
            delete [] Anim−>m_RotationKeys;
            Anim−>m_NumRotationKeys = NumKeys;
            Anim−>m_RotationKeys = new cAnimationQuaternionKey[NumKeys];
            	for(i=0;i<NumKeys;i++) {
            // Get time
            Anim−>m_RotationKeys[i].m_Time = *DataPtr++;
            		if(Anim−>m_RotationKeys[i].m_Time > m_AnimationSets−>m_Length)
            m_AnimationSets−>m_Length = Anim−>m_RotationKeys[i].m_Time;
            		// Skip # keys to follow (should be 4)
            DataPtr++;
            		// Get rotational values
            		float *fPtr = (float*)DataPtr;
            		Anim−>m_RotationKeys[i].m_quatKey.w = *fPtr++;
            Anim−>m_RotationKeys[i].m_quatKey.x = *fPtr++;
            Anim−>m_RotationKeys[i].m_quatKey.y = *fPtr++;
            Anim−>m_RotationKeys[i].m_quatKey.z = *fPtr++;
            		DataPtr+=4;
            }
            	break;

            You'll recall from earlier in this chapter that rotation keys use quaternion values. These values are stored in w, x, y, z order; to make sure you use the proper values, you must read them into the key's quaternion object appropriately.

            Next comes the code to load in the scaling and translation keys, which both use vectors to store the x−, y−, and z−axis information.

            case 1: // Scaling
            delete [] Anim−>m_ScaleKeys;
            Anim−>m_NumScaleKeys = NumKeys;
            Anim−>m_ScaleKeys = new cAnimationVectorKey[NumKeys];
            	for(i=0;i<NumKeys;i++) {
            // Get time
            Anim−>m_ScaleKeys[i].m_Time = *DataPtr++;
            		if(Anim−>m_ScaleKeys[i].m_Time > m_AnimationSets−>m_Length)
            m_AnimationSets−>m_Length = Anim−>m_ScaleKeys[i].m_Time;
            		// Skip # keys to follow (should be 3)
            DataPtr++;
            		// Get scale values
            D3DXVECTOR3 *vecPtr = (D3DXVECTOR3*)DataPtr;
            Anim−>m_ScaleKeys[i].m_vecKey = *vecPtr;
            DataPtr+=3;
            }
            	break;
            case 2: // Translation
            delete [] Anim−>m_TranslationKeys;
            Anim−>m_NumTranslationKeys = NumKeys;
            Anim−>m_TranslationKeys = new cAnimationVectorKey[NumKeys];
            	for(i=0;i<NumKeys;i++) {
            // Get time
            Anim−>m_TranslationKeys[i].m_Time = *DataPtr++;
            		if(Anim−>m_TranslationKeys[i].m_Time > m_AnimationSets−>m_Length)
            m_AnimationSets−>m_Length = Anim−>m_TranslationKeys[i].m_Time;
            		// Skip # keys to follow (should be 3)
            DataPtr++;
            		// Get translation values
            D3DXVECTOR3 *vecPtr = (D3DXVECTOR3*)DataPtr;
            Anim−>m_TranslationKeys[i].m_vecKey = *vecPtr;
            DataPtr+=3;
            }
            	break;

            Last is the code to read an array of transformation matrix keys.

            	case 4: // Transformation matrix
            delete [] Anim−>m_MatrixKeys;
            Anim−>m_NumMatrixKeys = NumKeys;
            Anim−>m_MatrixKeys = new cAnimationMatrixKey[NumKeys];
            		for(i=0;i<NumKeys;i++) {
            // Get time
            Anim−>m_MatrixKeys[i].m_Time = *DataPtr++;
            			if(Anim−>m_MatrixKeys[i].m_Time > m_AnimationSets−>m_Length)
            m_AnimationSets−>m_Length = Anim−>m_MatrixKeys[i].m_Time;
            			// Skip # keys to follow (should be 16)
            DataPtr++;
            			// Get matrix values
            D3DXMATRIX *mPtr = (D3DXMATRIX *)DataPtr;
            Anim−>m_MatrixKeys[i].m_matKey = *mPtr;
            DataPtr += 16;
            }
            		break;
            }
            }

            Okay now, take a quick breather and look back at what you've just accomplished. So far, you've processed every AnimationSet, Animation, and AnimationKey object (not to mention referenced Frame objects that contain the bones' names), plus you've loaded the key objects full of the animation data. You're almost ready to start animating!

            Almost is right; there is one small step left: matching the animation objects to their respective bone objects.


            posted on 2008-04-24 19:27 lovedday 閱讀(284) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            日韩精品久久久久久久电影| 精品久久久久久无码中文字幕一区| 久久r热这里有精品视频| 精品久久人妻av中文字幕| 91精品国产乱码久久久久久| 国产成人精品久久亚洲高清不卡| 久久久久国产日韩精品网站| 久久婷婷国产综合精品 | 久久精品aⅴ无码中文字字幕不卡 久久精品aⅴ无码中文字字幕重口 | 久久夜色精品国产噜噜亚洲a| 国产亚洲美女精品久久久2020| 精品免费久久久久久久| 国产精品久久久久免费a∨| 成人国内精品久久久久影院| 久久婷婷人人澡人人| 久久99国产精品久久久| 免费精品久久天干天干| 精品人妻伦九区久久AAA片69 | 亚洲伊人久久大香线蕉苏妲己| 色播久久人人爽人人爽人人片AV| 欧美精品一本久久男人的天堂| 亚洲AV无码久久精品蜜桃| 亚洲国产婷婷香蕉久久久久久| 久久er国产精品免费观看2| 亚洲级αV无码毛片久久精品| 亚洲国产成人精品女人久久久| 91久久精品无码一区二区毛片| 99久久99久久久精品齐齐| 日韩精品久久久久久久电影蜜臀| 久久精品无码一区二区app| 久久综合中文字幕| 成人妇女免费播放久久久| 少妇久久久久久久久久| 青青草原精品99久久精品66| 伊人久久大香线蕉AV色婷婷色 | 国产精品永久久久久久久久久| 成人久久久观看免费毛片| AAA级久久久精品无码片| 亚洲国产成人久久综合碰碰动漫3d | 国产精品久久99| 久久久久四虎国产精品|