参考他人的文章
修改 ETM,用Ogre实现《天龙八部》地形与部分场景详解(附源码)
纹理的创建方法和该文一样, 只是我打不算用ETM管理器创建地形
自己创建一个mesh来管理地形, 包含顶点数据, 纹理数据
修改 ETM,用Ogre实现《天龙八部》地形与部分场景详解(附源码)
纹理的创建方法和该文一样, 只是我打不算用ETM管理器创建地形
自己创建一个mesh来管理地形, 包含顶点数据, 纹理数据
1
void
TLBBTerrain::createManualMesh()
2 {
3
4 MeshPtr mesh = MeshManager::getSingleton().createManual( " mymesh " ,
5 ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
6 SubMesh * submesh = mesh -> createSubMesh();
7 submesh -> useSharedVertices = false ;
8
9 // 顶点缓存
10 submesh -> vertexData = new VertexData();
11 submesh -> vertexData -> vertexStart = 0 ;
12 unsigned int nCount = m_xSize * m_zSize * 4 ;
13 submesh -> vertexData -> vertexCount = nCount;
14
15 VertexDeclaration * decl = submesh -> vertexData -> vertexDeclaration;
16 VertexBufferBinding * bind = submesh -> vertexData -> vertexBufferBinding;
17
18 size_t offset = 0 ;
19 decl -> addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_POSITION);
20 offset += VertexElement::getTypeSize(VET_FLOAT3);
21
22 decl -> addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_NORMAL);
23 offset += VertexElement::getTypeSize(VET_FLOAT3);
24
25 decl -> addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0 );
26 offset += VertexElement::getTypeSize(VET_FLOAT2);
27
28 decl -> addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1 );
29 offset += VertexElement::getTypeSize(VET_FLOAT2);
30
31 decl -> addElement( MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 2 );
32 offset += VertexElement::getTypeSize(VET_FLOAT2);
33
34 HardwareVertexBufferSharedPtr vertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
35 decl -> getVertexSize(MAIN_BINDING), nCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
36 bind -> setBinding(MAIN_BINDING, vertexBuffer);
37
38 float * pBase = static_cast < float *> (vertexBuffer -> lock (HardwareBuffer::HBL_DISCARD));
39
40 TexureInfo info;
41
42 for ( int j = 0 ; j < m_zSize; ++ j)
43 {
44 for ( int i = 0 ; i < m_xSize; ++ i)
45 {
46 info = handleTexture(i, j);
47
48 // 点0
49 fillVertexData(i, j, pBase, info.firstleft, info.firsttop, info.secondleft, info.secondtop);
50 pBase += 12 ;
51
52 // 点1
53 fillVertexData(i, j + 1 , pBase, info.firstleft, info.firstbottom, info.secondleft, info.secondbottom);
54 pBase += 12 ;
55
56 // 点2
57 fillVertexData(i + 1 , j + 1 , pBase, info.firstright, info.firstbottom, info.secondright, info.secondbottom);
58 pBase += 12 ;
59
60 // 点3
61 fillVertexData(i + 1 , j, pBase, info.firstright, info.firsttop, info.secondright, info.secondtop);
62 pBase += 12 ;
63 }
64 }
65
66 vertexBuffer -> unlock();
67
68 HardwareIndexBufferSharedPtr indexBuffer =
69 HardwareBufferManager::getSingleton().createIndexBuffer(
70 HardwareIndexBuffer::IT_32BIT,
71 m_xSize * m_zSize * 6 ,
72 HardwareBuffer::HBU_STATIC, true );
73
74 submesh -> indexData -> indexBuffer = indexBuffer;
75 submesh -> indexData -> indexStart = 0 ;
76 submesh -> indexData -> indexCount = m_xSize * m_zSize * 6 ;
77 unsigned int * indexBuff = (unsigned int * )indexBuffer -> lock (HardwareBuffer::HBL_NORMAL);
78 int indexFirstNum = 0 ;
79 for ( int j = 0 ; j < m_zSize; ++ j)
80 {
81 for ( int i = 0 ; i < m_xSize; ++ i)
82 {
83 * indexBuff ++ = indexFirstNum;
84 * indexBuff ++ = indexFirstNum + 1 ;
85 * indexBuff ++ = indexFirstNum + 2 ;
86
87 * indexBuff ++ = indexFirstNum;
88 * indexBuff ++ = indexFirstNum + 2 ;
89 * indexBuff ++ = indexFirstNum + 3 ;
90 indexFirstNum += 4 ;
91 }
92 }
93
94 indexBuffer -> unlock();
95
96 AxisAlignedBox meshBounds( 0 , m_minHeight * m_scale.y, 0 ,
97 m_xSize * m_scale.x, m_maxHeight * m_scale.y, m_zSize * m_scale.z);
98 mesh -> _setBounds(meshBounds);
99 mesh -> load();
100 mesh -> touch();
101
102 // 设置相机位置
103 mSceneMgr -> getCamera( " PlayerCam " ) -> setPosition( 0 , m_maxHeight * m_scale.y, 0 );
104 }
2 {
3
4 MeshPtr mesh = MeshManager::getSingleton().createManual( " mymesh " ,
5 ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
6 SubMesh * submesh = mesh -> createSubMesh();
7 submesh -> useSharedVertices = false ;
8
9 // 顶点缓存
10 submesh -> vertexData = new VertexData();
11 submesh -> vertexData -> vertexStart = 0 ;
12 unsigned int nCount = m_xSize * m_zSize * 4 ;
13 submesh -> vertexData -> vertexCount = nCount;
14
15 VertexDeclaration * decl = submesh -> vertexData -> vertexDeclaration;
16 VertexBufferBinding * bind = submesh -> vertexData -> vertexBufferBinding;
17
18 size_t offset = 0 ;
19 decl -> addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_POSITION);
20 offset += VertexElement::getTypeSize(VET_FLOAT3);
21
22 decl -> addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_NORMAL);
23 offset += VertexElement::getTypeSize(VET_FLOAT3);
24
25 decl -> addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0 );
26 offset += VertexElement::getTypeSize(VET_FLOAT2);
27
28 decl -> addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1 );
29 offset += VertexElement::getTypeSize(VET_FLOAT2);
30
31 decl -> addElement( MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 2 );
32 offset += VertexElement::getTypeSize(VET_FLOAT2);
33
34 HardwareVertexBufferSharedPtr vertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
35 decl -> getVertexSize(MAIN_BINDING), nCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
36 bind -> setBinding(MAIN_BINDING, vertexBuffer);
37
38 float * pBase = static_cast < float *> (vertexBuffer -> lock (HardwareBuffer::HBL_DISCARD));
39
40 TexureInfo info;
41
42 for ( int j = 0 ; j < m_zSize; ++ j)
43 {
44 for ( int i = 0 ; i < m_xSize; ++ i)
45 {
46 info = handleTexture(i, j);
47
48 // 点0
49 fillVertexData(i, j, pBase, info.firstleft, info.firsttop, info.secondleft, info.secondtop);
50 pBase += 12 ;
51
52 // 点1
53 fillVertexData(i, j + 1 , pBase, info.firstleft, info.firstbottom, info.secondleft, info.secondbottom);
54 pBase += 12 ;
55
56 // 点2
57 fillVertexData(i + 1 , j + 1 , pBase, info.firstright, info.firstbottom, info.secondright, info.secondbottom);
58 pBase += 12 ;
59
60 // 点3
61 fillVertexData(i + 1 , j, pBase, info.firstright, info.firsttop, info.secondright, info.secondtop);
62 pBase += 12 ;
63 }
64 }
65
66 vertexBuffer -> unlock();
67
68 HardwareIndexBufferSharedPtr indexBuffer =
69 HardwareBufferManager::getSingleton().createIndexBuffer(
70 HardwareIndexBuffer::IT_32BIT,
71 m_xSize * m_zSize * 6 ,
72 HardwareBuffer::HBU_STATIC, true );
73
74 submesh -> indexData -> indexBuffer = indexBuffer;
75 submesh -> indexData -> indexStart = 0 ;
76 submesh -> indexData -> indexCount = m_xSize * m_zSize * 6 ;
77 unsigned int * indexBuff = (unsigned int * )indexBuffer -> lock (HardwareBuffer::HBL_NORMAL);
78 int indexFirstNum = 0 ;
79 for ( int j = 0 ; j < m_zSize; ++ j)
80 {
81 for ( int i = 0 ; i < m_xSize; ++ i)
82 {
83 * indexBuff ++ = indexFirstNum;
84 * indexBuff ++ = indexFirstNum + 1 ;
85 * indexBuff ++ = indexFirstNum + 2 ;
86
87 * indexBuff ++ = indexFirstNum;
88 * indexBuff ++ = indexFirstNum + 2 ;
89 * indexBuff ++ = indexFirstNum + 3 ;
90 indexFirstNum += 4 ;
91 }
92 }
93
94 indexBuffer -> unlock();
95
96 AxisAlignedBox meshBounds( 0 , m_minHeight * m_scale.y, 0 ,
97 m_xSize * m_scale.x, m_maxHeight * m_scale.y, m_zSize * m_scale.z);
98 mesh -> _setBounds(meshBounds);
99 mesh -> load();
100 mesh -> touch();
101
102 // 设置相机位置
103 mSceneMgr -> getCamera( " PlayerCam " ) -> setPosition( 0 , m_maxHeight * m_scale.y, 0 );
104 }
其实我认为, 可以根据主角在场景的位置创建小范围的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文件里面的同名文件
1
void
SkeletonSerializer::readAnimationTrack(DataStreamPtr
&
stream, Animation
*
anim,
2 Skeleton * pSkel)
3 {
4 // unsigned short boneIndex : Index of bone to apply to
5 unsigned short boneHandle;
6 readShorts(stream, & boneHandle, 1 );
7
8 // Find bone
9 Bone * targetBone = pSkel -> getBone(boneHandle);
10
11 // Create track
12 NodeAnimationTrack * pTrack = anim -> createNodeTrack(boneHandle, targetBone);
13
14 // Keep looking for nested keyframes
15 if ( ! stream -> eof())
16 {
17 unsigned short streamID = readChunk(stream);
18
19 // while(streamID == SKELETON_ANIMATION_TRACK_KEYFRAME && !stream->eof())
20 while ((streamID == SKELETON_ANIMATION_TRACK_KEYFRAME || streamID == 0x4120 ) && ! stream -> eof())
21 {
22 if (streamID == 0x4120 )
23 {
24 unsigned short len;
25 readShorts(stream, & len, 1 );
26 unsigned short flags;
27 readShorts(stream, & flags, 1 );
28
29 int count = (mCurrentstreamLen - 4 - 4 ) / 4 ;
30 if (len != count / 8 )
31 len = len;
32 float time;
33 for ( int i = 0 ; i < len; i += 1 )
34 {
35 readFloats(stream, & time, 1 );
36 TransformKeyFrame * kf = pTrack -> createNodeKeyFrame(time);
37
38 Quaternion rot = Quaternion::IDENTITY;
39 if (flags & 1 )
40 {
41 readObject(stream, rot);
42 }
43 kf -> setRotation(rot);
44
45 Vector3 trans = Vector3::ZERO;
46 if (flags & 2 )
47 {
48 readObject(stream, trans);
49 }
50 kf -> setTranslate(trans);
51 }
52 }
53 else
54 readKeyFrame(stream, pTrack, pSkel);
55
56 if ( ! stream -> eof())
57 {
58 // Get next stream
59 streamID = readChunk(stream);
60 }
61 }
62 if ( ! stream -> eof())
63 {
64 // Backpedal back to start of this stream if we've found a non-keyframe
65 stream -> skip( - STREAM_OVERHEAD_SIZE);
66 }
67
68 }
69
70 }
2 Skeleton * pSkel)
3 {
4 // unsigned short boneIndex : Index of bone to apply to
5 unsigned short boneHandle;
6 readShorts(stream, & boneHandle, 1 );
7
8 // Find bone
9 Bone * targetBone = pSkel -> getBone(boneHandle);
10
11 // Create track
12 NodeAnimationTrack * pTrack = anim -> createNodeTrack(boneHandle, targetBone);
13
14 // Keep looking for nested keyframes
15 if ( ! stream -> eof())
16 {
17 unsigned short streamID = readChunk(stream);
18
19 // while(streamID == SKELETON_ANIMATION_TRACK_KEYFRAME && !stream->eof())
20 while ((streamID == SKELETON_ANIMATION_TRACK_KEYFRAME || streamID == 0x4120 ) && ! stream -> eof())
21 {
22 if (streamID == 0x4120 )
23 {
24 unsigned short len;
25 readShorts(stream, & len, 1 );
26 unsigned short flags;
27 readShorts(stream, & flags, 1 );
28
29 int count = (mCurrentstreamLen - 4 - 4 ) / 4 ;
30 if (len != count / 8 )
31 len = len;
32 float time;
33 for ( int i = 0 ; i < len; i += 1 )
34 {
35 readFloats(stream, & time, 1 );
36 TransformKeyFrame * kf = pTrack -> createNodeKeyFrame(time);
37
38 Quaternion rot = Quaternion::IDENTITY;
39 if (flags & 1 )
40 {
41 readObject(stream, rot);
42 }
43 kf -> setRotation(rot);
44
45 Vector3 trans = Vector3::ZERO;
46 if (flags & 2 )
47 {
48 readObject(stream, trans);
49 }
50 kf -> setTranslate(trans);
51 }
52 }
53 else
54 readKeyFrame(stream, pTrack, pSkel);
55
56 if ( ! stream -> eof())
57 {
58 // Get next stream
59 streamID = readChunk(stream);
60 }
61 }
62 if ( ! stream -> eof())
63 {
64 // Backpedal back to start of this stream if we've found a non-keyframe
65 stream -> skip( - STREAM_OVERHEAD_SIZE);
66 }
67
68 }
69
70 }