Ogre 天龙八部地形管理器

最近研究天龙八部的地形管理, 由于地形很大, 很显然Ogre自带的地形管理器没法使用
参考了别人的研究之后, 不打算使用ETM来管理地形
直接写了一个巨大的手工纹理来保存地形所需要的所有图像, 然后根据网格数据一个一个填写纹理坐标, 
目前只写了地形第一层的代码, 第二层还没开始
读写速度还是很快的

下面是两张截图

Ogre 天龙八部地形管理器_第1张图片

参考他人的文章
修改 ETM,用Ogre实现《天龙八部》地形与部分场景详解(附源码) 
纹理的创建方法和该文一样, 只是我打不算用ETM管理器创建地形
自己创建一个mesh来管理地形, 包含顶点数据, 纹理数据

view source print ?
01 void TLBBTerrain::createManualMesh()
02 {
03     MeshPtr mesh = MeshManager::getSingleton().createManual("mymesh",
04         ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
05     SubMesh* submesh = mesh->createSubMesh();
06     submesh->useSharedVertices = false;
07     // 顶点缓存
08     submesh->vertexData = new VertexData();
09     submesh->vertexData->vertexStart = 0;
10     unsigned int nCount = m_xSize * m_zSize * 4;
11     submesh->vertexData->vertexCount = nCount;
12     VertexDeclaration* decl = submesh->vertexData->vertexDeclaration;
13     VertexBufferBinding* bind = submesh->vertexData->vertexBufferBinding;
14     size_t offset = 0;
15     decl->addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_POSITION);
16     offset += VertexElement::getTypeSize(VET_FLOAT3);
17     decl->addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_NORMAL);
18     offset += VertexElement::getTypeSize(VET_FLOAT3);
19     decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
20     offset += VertexElement::getTypeSize(VET_FLOAT2);
21     decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1);
22     offset += VertexElement::getTypeSize(VET_FLOAT2);
23     decl->addElement( MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 2);
24     offset += VertexElement::getTypeSize(VET_FLOAT2);
25     HardwareVertexBufferSharedPtr vertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
26         decl->getVertexSize(MAIN_BINDING), nCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
27     bind->setBinding(MAIN_BINDING, vertexBuffer);
28     float* pBase = static_cast<float*>(vertexBuffer->lock(HardwareBuffer::HBL_DISCARD));
29     TexureInfo info;
30     for (int j = 0; j < m_zSize; ++j)
31     {
32         for (int i = 0; i < m_xSize; ++i)
33         {
34             info = handleTexture(i, j);
35             // 点0
36             fillVertexData(i, j, pBase, info.firstleft, info.firsttop, info.secondleft, info.secondtop);
37             pBase += 12;
38             // 点1
39             fillVertexData(i, j+1, pBase, info.firstleft, info.firstbottom, info.secondleft, info.secondbottom);
40             pBase += 12;
41             // 点2
42             fillVertexData(i+1, j+1, pBase, info.firstright, info.firstbottom, info.secondright, info.secondbottom);
43             pBase += 12;
44             // 点3
45             fillVertexData(i+1, j, pBase, info.firstright, info.firsttop, info.secondright, info.secondtop);
46             pBase += 12;
47         }
48     }
49     vertexBuffer->unlock();
50     HardwareIndexBufferSharedPtr indexBuffer =
51         HardwareBufferManager::getSingleton().createIndexBuffer(
52         HardwareIndexBuffer::IT_32BIT,
53         m_xSize * m_zSize * 6,
54         HardwareBuffer::HBU_STATIC, true);
55     submesh->indexData->indexBuffer = indexBuffer;
56     submesh->indexData->indexStart = 0;
57     submesh->indexData->indexCount = m_xSize * m_zSize * 6;
58     unsigned int* indexBuff = (unsigned int*)indexBuffer->lock(HardwareBuffer::HBL_NORMAL);
59     int indexFirstNum = 0;
60     for (int j = 0; j < m_zSize; ++j)
61     {
62         for (int i = 0; i < m_xSize; ++i)
63         {
64             *indexBuff++ = indexFirstNum;
65             *indexBuff++ = indexFirstNum + 1;
66             *indexBuff++ = indexFirstNum + 2;
67             *indexBuff++ = indexFirstNum;
68             *indexBuff++ = indexFirstNum + 2;
69             *indexBuff++ = indexFirstNum + 3;
70             indexFirstNum += 4;
71         }
72     }
73     indexBuffer->unlock();
74     AxisAlignedBox meshBounds(0, m_minHeight * m_scale.y, 0,
75         m_xSize * m_scale.x, m_maxHeight * m_scale.y, m_zSize * m_scale.z);
76     mesh->_setBounds(meshBounds);
77     mesh->load();
78     mesh->touch();
79     // 设置相机位置
80     mSceneMgr->getCamera("PlayerCam")->setPosition(0, m_maxHeight * m_scale.y, 0);
81 }

其实我认为, 可以根据主角在场景的位置创建小范围的mesh, 可以将该mesh分成tile*tile大小, 根据主角位置创建周围四个tile的mesh就可以了. 不需要写这么大的mesh.等以后写入主角怪物的时候在写这段代码

加载静态对象的时候出现了很多问题, 经过分析, 发现天龙八部游戏新版本的很多mesh不能够直接使用, 主要是Model目录里面的0灌木, 0树木, 0物品三个文件夹里面的mesh文件
直接拷贝老天龙的数据就可以了
不过加载的时候读取skeleton数据会出现错误, 查找一些资料后发现需要直接修改Ogre源码, 这些数据主要用于实现骨骼动画的时候会出现
对OgreSkeletonSerializer.cpp文件里面的SkeletonSerializer::readAnimationTrack 函数进行修改.然后编译出ogremain.dll, ogremain_d.lib, 覆盖OgreSDK/bin文件里面的同名文件

view source print ?
01 void   SkeletonSerializer::readAnimationTrack(DataStreamPtr  &   stream, Animation  *   anim,
02        Skeleton *  pSkel)
03    {
04         //  unsigned short boneIndex     : Index of bone to apply to
05        unsigned  short  boneHandle;
06        readShorts(stream,  & boneHandle,  1 );
07         //  Find bone
08        Bone  * targetBone  =  pSkel -> getBone(boneHandle);
09         //  Create track
10        NodeAnimationTrack *  pTrack  =  anim -> createNodeTrack(boneHandle, targetBone);
11         //  Keep looking for nested keyframes
12         if  ( ! stream -> eof())
13        {
14            unsigned  short  streamID  =  readChunk(stream);
15             // while(streamID == SKELETON_ANIMATION_TRACK_KEYFRAME && !stream->eof())
16             while ((streamID  ==  SKELETON_ANIMATION_TRACK_KEYFRAME  ||  streamID  ==   0x4120 )  &&   ! stream -> eof())
17            {
18                 if  (streamID  ==   0x4120 )
19                {
20                    unsigned  short  len;
21                    readShorts(stream,  & len,  1 );
22                    unsigned  short  flags;
23                    readShorts(stream,  & flags,  1 );
24                     int  count  =  (mCurrentstreamLen  -   4   -   4 )  /   4 ;
25                     if  (len  !=  count  /   8 )
26                        len  =  len;
27                     float  time;
28                     for  ( int  i  =   0 ; i  <  len; i  +=   1 )
29                    {
30                        readFloats(stream,  & time,  1 );
31                        TransformKeyFrame  * kf  =  pTrack -> createNodeKeyFrame(time);
32                        Quaternion rot  =  Quaternion::IDENTITY;
33                         if  (flags  &   1 )
34                        {
35                            readObject(stream, rot);
36                        }
37                        kf -> setRotation(rot);
38                        Vector3 trans  =  Vector3::ZERO;
39                         if  (flags  &   2 )
40                        {
41                            readObject(stream, trans);
42                        }
43                        kf -> setTranslate(trans);
44                    }
45                }
46                 else
47                    readKeyFrame(stream, pTrack, pSkel);
48                 if  ( ! stream -> eof())
49                {
50                     //  Get next stream
51                    streamID  =  readChunk(stream);
52                }
53            }
54             if  ( ! stream -> eof())
55            {
56                 //  Backpedal back to start of this stream if we've found a non-keyframe
57                stream -> skip( - STREAM_OVERHEAD_SIZE);
58            }
59        }
60    }

显示场景图如下

Ogre 天龙八部地形管理器_第2张图片

你可能感兴趣的:(Ogre 天龙八部地形管理器)