菜鸟学习OGRE和天龙八部之七: frame帧动画数据格式搞定,已修正关键帧

来源:互联网 发布:ido软件中文 编辑:程序博客网 时间:2024/05/17 23:28

准备破解frame数据格式,用UE打开一开,很明显的发现了Serializer_v1.10这几个字样,很明显,是采用Serializer这个类来写入的

而且应该是SkeletonSerializer,为了验证,UE看看二进制代码,先看看此类的几个文件块枚举

    enum SkeletonChunkID {
        SKELETON_HEADER            = 0x1000,
        SKELETON_BONE              = 0x2000,

        SKELETON_BONE_PARENT       = 0x3000,

        SKELETON_ANIMATION         = 0x4000,

        SKELETON_ANIMATION_TRACK = 0x4100,

        SKELETON_ANIMATION_TRACK_KEYFRAME = 0x4110,
        SKELETON_ANIMATION_LINK         = 0x5000

};

 

如果文件中的存在此类文件块,说明猜测正确.

用UE看,可以找出00 10 和00 40之类,说明就是一个Skeleton文件,转换成XML看看:


加载进去数据少了keyframes,原来天龙自己定义的帧类型,数据放置的文件块位置的枚举是0x4120,而不是0x4110

不过里面存的内容应该是一样的,上网找找,有大侠已经提供了相关函数了:

添加天龙自定义的Keyframe类型,该类型应该是用于减少内存的
SKELETON_ANIMATION_TRACK_KEYFRAME_OPTIMIZE  0x4120 (16672)

在OgreSkeletonSerializer.cpp中修改:
void SkeletonSerializer::readAnimationTrack(DataStreamPtr& stream, Animation* anim, Skeleton* pSkel)
{
    //...
        // Keep looking for nested keyframes
        if (!stream->eof())
        {
            unsigned short streamID = readChunk(stream);
            while( (streamID == SKELETON_ANIMATION_TRACK_KEYFRAME || 
            streamID == SKELETON_ANIMATION_TRACK_KEYFRAME_OPTIMIZE)
                && !stream->eof())
            {
                if (streamID == SKELETON_ANIMATION_TRACK_KEYFRAME_OPTIMIZE)
                {
                    // 新增代码
                    unsigned short len;
                    unsigned short flags;
                    readShorts(stream, &len, 1);
                    readShorts(stream, &flags, 1);

                    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);

                        //网上流行的解析代码,少了这部分,导致有些动画解析不正确,比如柳枝的摆动
                        //很多场景中的StaticEntity都包含柳树的骨骼动画                        
                        Vector3 scale = Vector3::UNIT_SCALE;
                        if (flags & 4)
                        {
                            readObject(stream, scale);
                        }
                        kf->setScale(scale);
                    }
                }
                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源码有点违反开源精神....,自己写了一个类来载入,这下数据正常了,如图: