关于Ogre的主角模型,纹理加载

来源:互联网 发布:淘宝店铺怎么卖东西 编辑:程序博客网 时间:2024/04/28 22:56

因为马上毕业了,加之自己在学习ogre,还在网上找到点天龙八部的资源,所以,就想毕业设计做个MMORPG的游戏,当然只是做个大概,我可没这种实力和时间做这种东西,主要还是学习ogre的目的了

好了,言归正传,我刚刚用我自己的土办法完成了天龙八部的主角模型的加载,网上有很多关于天龙八部模型加载的文章,但是,基本上没有一个认真的讲过主角模型的加载,都只是给出效果图,说几句话,很多细节没讲清楚。然后,我在一些ogre的技术群问一些问题的时候,群里老是有几个装B的人说天龙八部怎么不好,就是不说怎么解决问题,在次,我写下我的经验,顺便BS一下那些人,不要用鄙视别人的作品来抬高自己的身价,不会就不要说话。

我的这些办法是我自己想的土办法,有很多地方我也觉得不对,如果你有更好的处理方法,我希望能够给我留言,给我点指导

当然,加载天龙八部模型的第一步就是要修改骨骼加载函数了,本来不应该修改ogre源代码的,但是,貌似,没做多大的修改,好像就是改了最大的骨骼数,所以,我还是修改了源代码,修改以后还是可以加载ogre例子中的模型,以及骨骼动画,所以,我觉得,没什么影响。

修改ogre源代码(我用的ogre1.72) SkeletonSerializer.cpp文件的: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 && !stream->eof())
        //    {
        //        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);
        //    }


        //}


if (!stream->eof())
{
unsigned short streamID = readChunk(stream);
while( (streamID == SKELETON_ANIMATION_TRACK_KEYFRAME || 
streamID == 0x4120)
&& !stream->eof())
{
if (streamID == 0x4120)
{
// 新增代码
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);
}
}
    }

修改完以后,就基本上可以加载天龙八部的模型了

虽然,可能读者知道,但是,我还是不得不提醒一下,如果你发现你加载的模型没有纹理,那么你就要写个材质的脚本了

例如:一个.material的文件


还有一个比较如果出现异常的地方,你在加载中文的mesh文件,纹理,骨骼文件时候可能会报错,说文件找不到,这是因为 ,ogre因为一些原因不能支持中文,网上有一篇文章是讲怎么改文件读取代码的,但是,我觉得还是不要改好,毕竟,ogre是一个跨平台的,你用微软的写了再编译始终不太好,我有一个很简单的方法,就是在程序中申明我现在的操作系统,使用的字符格式,使用下面的函数就可以做到,最好在整个程序的开始就加入

setlocale(LC_ALL,"Chinese-simplified");

很简单的一个函数

你在看天龙八部模型的时候,可能会发现很多的模型是被裁开的,是多个文件,这样做是为了换装系统的实现,还有就是变异BB之类的,呵呵

下面我就拿天龙八部资源里面的女主角来说明一下,我的做法,因为我写的时候实在是没注意源码的格式,只是做个实验的性质的,代码写得实在太丑,如果我直接贴代码上来的话,估计会被人嘲笑,所以,我就讲讲主要的思路,如果你有什么不明白的,可以给我留言,我一定会尽我所能回答

下面进入正题

当你发现一个角色有很多模型的时候,其实组装他们很简单,因为美工做这些模型的时候,本地坐标的相对位置都是调节好了的,所以,你把每个模型读出了,得到一堆Ogre::Entity,然后把每个模型分别绑定到一个场景节点上,然后把这些场景节点绑定到一个主场景节点上,在操作角色的时候,就可以通过操作这个主场景节点来实现了。

还有就是模型的动画了,你可以用ogre的二进制转换工具OgreXMLConverter.exe来讲二进制的模型,以及骨骼文件转换为xml文件来查看,同时,会生成一个log文件,里面记录了很多关于骨骼以及动画名之类的东西,相当有用,当然,你要转换天龙八部的文件,就不得不用按照上面的方法修改ogre源码,然后重新生成OgreXMLConverter.exe了

你要想主角所有部分都播放动画,肯定要创建一个容器来装每个部分动画的Ogre::AnimationStat指针,以便于在渲染的时候更新时间,和修改当前的播放动画


可能你还需要加载武器,那么就请你在你的文件夹中查找女主角.obj这个文件,上面有武器的挂载点,四元数变换值,以及位置调整坐标等信息‘,用这些信息,你就可以把武器加载到角色的手上了,当然你是要把武器直接挂载到角色手臂骨骼上去的,用



最后喃,就是坐骑部分了,我现在还没有想出一个很好的办法来做它,虽然,我实现了,但是,我不鼓励大家用我这个方法来实现坐骑,因为,我是把坐骑读出来以一个节点绑定到主角主节点上的,但是,我发现坐骑那个文件夹下面每个坐骑都有个obj文件,里面记录了坐骑的挂载点,我通过查看坐骑的骨骼文件,发现,好像天龙八部是想把人物挂到坐骑上去,我这个地方就搞不定了,如果挂载骨骼的话,就必须是一个Ogre::MovableObject的指针,但是,主角,我是用一个主节点来整合的,场景节点不是Ogre::MovableObject类型的,所以,我觉得我这图办法是有问题的,希望知道的人给我解答我的疑惑