您的位置:首页 > 其它

Ogre 天龙八部地形管理器

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

下面是两张截图





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

view sourceprint?

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 sourceprint?

01
void
SkeletonSerializer::readAnimationTrack(DataStreamPtr  &stream, Animation  *anim,
02
Skeleton *  pSkel)
03
{
04
//  unsignedshort 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
}
显示场景图如下

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: