参考他人的文章
修改 ETM,用Ogre实现《天龙八部》地形与部分场景详解(附源码)
纹理的创建方法和该文一样, 只是我打不算用ETM管理器创建地形
自己创建一个mesh来管理地形, 包含顶点数据, 纹理数据
01 | void TLBBTerrain::createManualMesh() |
03 | MeshPtr mesh = MeshManager::getSingleton().createManual( "mymesh" , |
04 | ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); |
05 | SubMesh* submesh = mesh->createSubMesh(); |
06 | submesh->useSharedVertices = false ; |
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; |
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)); |
30 | for ( int j = 0; j < m_zSize; ++j) |
32 | for ( int i = 0; i < m_xSize; ++i) |
34 | info = handleTexture(i, j); |
36 | fillVertexData(i, j, pBase, info.firstleft, info.firsttop, info.secondleft, info.secondtop); |
39 | fillVertexData(i, j+1, pBase, info.firstleft, info.firstbottom, info.secondleft, info.secondbottom); |
42 | fillVertexData(i+1, j+1, pBase, info.firstright, info.firstbottom, info.secondright, info.secondbottom); |
45 | fillVertexData(i+1, j, pBase, info.firstright, info.firsttop, info.secondright, info.secondtop); |
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) |
62 | for ( int i = 0; i < m_xSize; ++i) |
64 | *indexBuff++ = indexFirstNum; |
65 | *indexBuff++ = indexFirstNum + 1; |
66 | *indexBuff++ = indexFirstNum + 2; |
67 | *indexBuff++ = indexFirstNum; |
68 | *indexBuff++ = indexFirstNum + 2; |
69 | *indexBuff++ = indexFirstNum + 3; |
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); |
80 | mSceneMgr->getCamera( "PlayerCam" )->setPosition(0, m_maxHeight * m_scale.y, 0); |
其实我认为, 可以根据主角在场景的位置创建小范围的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文件里面的同名文件
01 | void SkeletonSerializer::readAnimationTrack(DataStreamPtr & stream, Animation * anim, |
05 | unsigned short boneHandle; |
06 | readShorts(stream, & boneHandle, 1 ); |
08 | Bone * targetBone = pSkel -> getBone(boneHandle); |
10 | NodeAnimationTrack * pTrack = anim -> createNodeTrack(boneHandle, targetBone); |
12 | if ( ! stream -> eof()) |
14 | unsigned short streamID = readChunk(stream); |
16 | while ((streamID == SKELETON_ANIMATION_TRACK_KEYFRAME || streamID == 0x4120 ) && ! stream -> eof()) |
18 | if (streamID == 0x4120 ) |
21 | readShorts(stream, & len, 1 ); |
23 | readShorts(stream, & flags, 1 ); |
24 | int count = (mCurrentstreamLen - 4 - 4 ) / 4 ; |
25 | if (len != count / 8 ) |
28 | for ( int i = 0 ; i < len; i += 1 ) |
30 | readFloats(stream, & time , 1 ); |
31 | TransformKeyFrame * kf = pTrack -> createNodeKeyFrame( time ); |
32 | Quaternion rot = Quaternion::IDENTITY; |
35 | readObject(stream, rot); |
37 | kf -> setRotation(rot); |
38 | Vector3 trans = Vector3::ZERO; |
41 | readObject(stream, trans); |
43 | kf -> setTranslate(trans); |
47 | readKeyFrame(stream, pTrack, pSkel); |
48 | if ( ! stream -> eof()) |
51 | streamID = readChunk(stream); |
54 | if ( ! stream -> eof()) |
57 | stream -> skip( - STREAM_OVERHEAD_SIZE); |
显示场景图如下