如何加载《天龙八部》Skeleton

如何加载《天龙八部》Skeleton

说明:本文章纯属学习之用,如有商业之用,与本人无关。

网络游戏《天龙八部》采用的是Ogre3d作为其客户端渲染引擎,他们对之做了许多自定义的修改,在这里作为学习只用,特别说明一下其自定义的Skeleton的格式,以及如何加载的办法。

天龙八部加入了这样一个区段:
SKELETON_ANIMATION_TRACK_MULTI_KEYFRAME   0x4120  ( 16672 )
在加入了这个区段的内容之后,其格式大概就是这样一个样子:
  enum  SkeletonChunkID {
        SKELETON_HEADER            
=   0x1000 ,
            
//  char* version           : Version number check
        SKELETON_BONE               =   0x2000 ,
        
//  Repeating section defining each bone in the system. 
        
//  Bones are assigned indexes automatically based on their order of declaration
        
//  starting with 0.

            
//  char* name                       : name of the bone
            
//  unsigned short handle            : handle of the bone, should be contiguous & start at 0
            
//  Vector3 position                 : position of this bone relative to parent 
            
//  Quaternion orientation           : orientation of this bone relative to parent 
            
//  Vector3 scale                    : scale of this bone relative to parent 

        SKELETON_BONE_PARENT       
=   0x3000 ,
        
//  Record of the parent of a single bone, used to build the node tree
        
//  Repeating section, listed in Bone Index order, one per Bone

            
//  unsigned short handle             : child bone
            
//  unsigned short parentHandle   : parent bone

        SKELETON_ANIMATION         
=   0x4000 ,
        
//  A single animation for this skeleton

            
//  char* name                       : Name of the animation
            
//  float length                      : Length of the animation in seconds

            SKELETON_ANIMATION_TRACK 
=   0x4100 ,
            
//  A single animation track (relates to a single bone)
            
//  Repeating section (within SKELETON_ANIMATION)
                
                
//  unsigned short boneIndex     : Index of bone to apply to

                SKELETON_ANIMATION_TRACK_KEYFRAME 
=   0x4110 ,
                
//  A single keyframe within the track
                
//  Repeating section

                    
//  float time                    : The time position (seconds)
                    
//  Quaternion rotate            : Rotation to apply at this keyframe
                    
//  Vector3 translate            : Translation to apply at this keyframe
                    
//  Vector3 scale                : Scale to apply at this keyframe

                SKELETON_ANIMATION_TRACK_MULTI_KEYFRAME 
=   0x4120 ,
                
//  A multiple keyframe within the track
                
//  Repeating section

                    
//  float length                 : Length of the animation in seconds
                    
//  float flags                  : Length of the animation in seconds
                        
//  float time                   : The time position (seconds)
                        
//  Quaternion rotate            : Rotation to apply at this keyframe
                        
//  Vector3 translate            : Translation to apply at this keyframe
                
        SKELETON_ANIMATION_LINK         
=   0x5000
        
//  Link to another skeleton, to re-use its animations

            
//  char* skeletonName                    : name of skeleton to get animations from
            
//  float scale                            : scale to apply to trans/scale keys

    };


然后我们打开OgreSkeletonSerializer.cpp找到SkeletonSerializer::readAnimationTrack的实现,然后替换为下面的代码:
void  SkeletonSerializer::readAnimationTrack(DataStreamPtr &  stream, Animation *  anim, 
        Skeleton
*  pSkel)
    {
        
//  unsigned short boneIndex     : Index of bone to apply to
        unsigned  short  boneHandle;
        readShorts(stream, 
& boneHandle,  1 );

        
//  Find bone
        Bone  * targetBone  =  pSkel -> getBone(boneHandle);

        
//  Create track
        NodeAnimationTrack *  pTrack  =  anim -> createNodeTrack(boneHandle, targetBone);

        
//  Keep looking for nested keyframes
         if  ( ! stream -> eof())
        {
            unsigned 
short  streamID  =  readChunk(stream);
            
while ( (streamID  ==  SKELETON_ANIMATION_TRACK_KEYFRAME  ||  streamID  ==  SKELETON_ANIMATION_TRACK_MULTI_KEYFRAME)
                
&&   ! stream -> eof())
            {
                
if  (streamID  ==  SKELETON_ANIMATION_TRACK_MULTI_KEYFRAME)
                {
                    
//  TLBB 新增了此部分
                    unsigned  short  len;
                    unsigned 
short  flags;
                    readShorts(stream, 
& len,  1 );
                    readShorts(stream, 
& flags,  1 );

                    
int  count  =  (mCurrentstreamLen  -   4   -   4 /   4 ;
                    
if  (len  !=  count  /   8 )
                    {
                        len 
=  len;
                    }
                    
float  time;
                    
for  ( int  i  =   0 ; i  <  len; i  +=   1 )
                    {
                        readFloats(stream, 
& time,  1 );
                        TransformKeyFrame 
* kf  =  pTrack -> createNodeKeyFrame(time);

                        Quaternion rot 
=  Quaternion::IDENTITY;
                        
if  (flags  &   1 )
                        {
                            readObject(stream, rot);
                        }
                        kf
-> setRotation(rot);

                        Vector3 trans 
=  Vector3::ZERO;
                        
if  (flags  &   2 )
                        {
                            readObject(stream, trans);
                        }
                        kf
-> setTranslate(trans);
                    }
                }
                
else
                {
                    readKeyFrame(stream, pTrack, pSkel);
                }

                
if  ( ! stream -> eof())
                {
                    
//  Get next stream
                    streamID  =  readChunk(stream);
                }
            }
           
            
if  ( ! stream -> eof())
            {
                
//  Backpedal back to start of this stream if we've found a non-keyframe
                stream -> skip( - STREAM_OVERHEAD_SIZE);
            }
        }
    }
保存然后重新编译Ogre就OK了,理论上就是可以加载其骨骼动画了。
另外,其骨骼文件名,模型文件名都是用的中文,而VS2005对中文路径名的支持是有一个bug的,解决此问题参见下面这篇文章:
http://www.cppblog.com/tx7do/archive/2008/12/09/68897.html


你可能感兴趣的:(如何加载《天龙八部》Skeleton)