有个网友说他把我csdn博客的零落代码拼起来搞了一周都没能够载入场景....
真的蛮辛苦的....天龙的地形用mesh自己做就好的,
以前我的部分源码效率有问题,因为我低估了tostring函数的开销,
这函数很变态....用io输出流来实现的,代码优雅但是效率就....
如果需要多次循环就不要使用它.
好了,发源码,随便说一句,csdn很烂.....提交老是失败,实在受不了~~~
头文件:
1
/**//*
2
**************************************************************************************************************
3
@fileName Terrain.h
4
@remarks 用来创建地形,和保存地形相关信息
5
@author LYN 2009.10.1
6
***************************************************************************************************************
7
*/
8
#pragma once
9
10
#include "TLBB.h"
11
#include <vector>
12
using namespace Ogre;
13
using std::vector;
14
15
const uint TERRAIN_QUERY_MASK = 0x00000001; // 地形查询掩码
16
const unsigned short MAIN_BINDING = 0; // 主绑定
17
18
/**//* 网格操作标志的枚举*/
19
enum Operate
20

{
21
FLIP_HORIZINTAL = 1, // 图片水平翻转,即左右翻转
22
FLIP_VERTICAL = 2, // 图片垂直翻转,即上下翻转
23
ANTICLOCKWISE_90 = 4, // 逆时针旋转90度
24
FLIP_DIAGONAL = 8 // 三角形的对角线镜像,IndexOrder==0时就把左上的纹理坐标复制到右下,否则右上到左下
25
};
26
27
/**//* 像素图信息
28
@remarks 保存的是每个网格的纹理图片ID和纹理坐标
29
*/
30
struct PixMap
31

{
32
int textureId;
33
Real left;
34
Real top;
35
Real right;
36
Real bottom;
37
};
38
39
/**//* 高度图文件头信息*/
40
struct HeightMapHeader
41

{
42
DWORD nMagic;
43
DWORD nVersion; // 版本号
44
int nWidth;
45
int nHeight;
46
};
47
48
/**//* 碰撞图文件头*/
49
struct WCollisionHeader
50

{
51
DWORD nVersion;
52
DWORD nNumber; // 三角形数量
53
};
54
55
/**//* 网格文件头信息*/
56
struct GridHeader
57

{
58
DWORD nMagic;
59
DWORD nVersion;
60
int nWidth;
61
int nHeight;
62
};
63
64
/**//* 单个网格类
65
@remarks 1个网格就是一个正方,天龙八部的地形是根据网格信息拼接而成,但没有共享顶点,这样可以做很多层uv
66
*/
67
class GridInfo
68

{
69
public:
70
// 第一层pixelmap的索引, 如果是7字节版本,读取后需交换高8位与低8位的值,
71
// 需做如下操作 nFirstLayer = (nFirstLayer<<8)|(nFirstLayer>>8)
72
short nFirstLayer;
73
74
// 对nFirstLayer的操作, 取值是上面几个定义的宏, 可以互相组合
75
BYTE nFirstLayerOp;
76
77
// 第二层pixelmap的索引, 天龙八部的地表不算光照图有两层UV来融合
78
short nSecondLayer;
79
80
// 对nSecondLayer的操作,取值同nFirstLayerOp
81
BYTE nSecondLayerOp;
82
83
// 对格子的三角形的操作,可能取值如下, 0正常三角形索引, 1不同于正常的三角形索引
84
BYTE IndexOrder;
85
};
86
87
/**//* TLBBTerrain类
88
@remarks 用来生成地形
89
*/
90
class TLBBTerrain
91

{
92
public:
93
/**//* 构造函数
94
@param filename 地形文件名
95
@param sceneMgr 场景管理器
96
*/
97
TLBBTerrain(const String& filename, SceneManager* sceneMgr);
98
~TLBBTerrain(void);
99
100
/**//* 生成地形
101
@remarks 生成地形,直接调用此方法直接可以生成地形.
102
*/
103
void createTerrain(void);
104
105
/**//* 获得地图X方向的缩放*/
106
int getScaleX(void) const;
107
108
/**//* 获得地图Y方向的缩放*/
109
int getScaleY(void) const;
110
111
/**//* 获得地图Z方向的缩放*/
112
int getScaleZ(void) const;
113
114
/**//* 获得地图X方向的大小*/
115
int getXSize(void) const;
116
117
/**//* 获得地图Z方向的大小*/
118
int getZSize(void) const;
119
120
/**//* 获得地图中心点*/
121
const Vector3& getCentre(void) const;
122
123
/**//* 获得高度图数据*/
124
const vector<Real>& getHeightMapData(void) const;
125
126
/**//* 获得手工材质的名字数组
127
@remarks 手动生成的材质换图的时候需要手工清除,所以保留他们的名字
128
*/
129
const vector<String>& getManualMatData(void) const;
130
131
/**//* 获得手工mesh的名字数组
132
@remarks 手动生成的mesh换图的时候需要手工清除,所以保留他们的名字
133
*/
134
const vector<String>& getManualMeshData(void) const;
135
136
/**//* 获得WCollision实体指针数组*/
137
const vector<Entity*>& getmWCollisionEntData(void) const;
138
139
protected:
140
141
/**//* 打开网格文件
142
@remarks 二进制流载入
143
@param filename 网格文件名
144
@param groupName 资源组名字
145
*/
146
void openGridFile(const String& fileName, const String &groupName);
147
148
/**//* 打开高度图文件
149
@remarks 二进制流载入
150
@param filename 高度图文件名
151
@param groupName 资源组名字
152
*/
153
void openHeightMapFile(const String &fileName, const String &groupName);
154
155
/**//* 翻转纹理图片
156
@remarks 对纹理图片的操作
157
*/
158
void flipPicture(int op, Vector2& TL, Vector2& TR, Vector2& BL, Vector2& BR, int indexOrder);
159
160
/**//* 查找此网格的材质是否已经生成了
161
@remarks 如果存在就不用再生成
162
@param gridinfo 资源组名字
163
@param endIndex 结束的索引,控制查询范围
164
@return 如果已经生成了,就返回含有此材质的那个网格的索引, 否则返回-1
165
*/
166
int findSameMaterial(GridInfo& gridinfo, int endIndex);
167
168
/**//* 手工生成材质
169
@remarks 克隆材质模板,再更改纹理别名即可
170
*/
171
void createManualMat(void);
172
173
/**//* 获得顶点法线
174
@remarks 为了简单,只获得网格法线,暂时没有求顶点法线,如果要想效果更好,求平均即可得到顶点法线
175
@param x 顶点缩放后的x坐标
176
@param z 顶点缩放后的z坐标
177
@return 法线坐标
178
*/
179
Vector3 getNormalAt(Real x, Real z) const;
180
181
/**//* 生成地形tile
182
@remarks 直接操作硬件缓存生成地形mesh
183
@param startx 没有缩放的x起点坐标
184
@param startz 没有缩放的z起点坐标
185
@param tileSizeX tile X方向的大小, 虽然天龙的tilesize都是32,但有的图不是tile整数倍,可以更改此值生成随意大小的tile,
186
@param tileSizeZ tile Z方向的大小
187
@param matName 材质名字
188
*/
189
bool createTileMesh(size_t startx, size_t startz, int tileSizeX, int tileSizeZ, const String& matName);
190
191
/**//* 生成地形tile
192
@remarks 用manualObject来做地形, 简单很多,经过测试和操作硬件缓存效率基本差不多,可以二选其一
193
@param startx 没有缩放的x起点坐标
194
@param startz 没有缩放的z起点坐标
195
@param tileSizeX tile X方向的大小, 虽然天龙的tilesize都是32,但有的图不是tile整数倍,可以更改此值生成随意大小的tile,
196
@param tileSizeZ tile Z方向的大小
197
@param matName 材质名字
198
*/
199
void createTileManualObject(size_t startx, size_t startz, int tileSizeX, int tileSizeZ, const String& matName);
200
201
/**//* 生成WCollision
202
@remarks WCollision用来地形查询用,不用渲染出来,所以应该按区域分开生成多个WCollision,以减少查询的顶点数量
203
@param fileName WCollision文件的名字
204
@param groupName 资源组
205
*/
206
void createWCollision(const String &fileName , const String &groupName);
207
208
protected:
209
210
// 场景管理器
211
SceneManager* mSceneMgr;
212
213
// 地图分块大小
214
int mTileSize;
215
216
// 地图大小和缩放
217
int mXSize;
218
int mZSize;
219
int mScaleX;
220
int mScaleY;
221
int mScaleZ;
222
223
// 地图中心点位置
224
Vector3 mCentre;
225
226
// 是否有光照图
227
bool mHasLightMap;
228
229
// 光照图文件名
230
String mLightMapName;
231
232
// 材质数量
233
size_t mMaterialNum;
234
235
// 高度图
236
vector<Real> mHeightMapData;
237
238
// 网格信息
239
vector<GridInfo> mGridData;
240
241
// 纹理
242
vector<String> mTextureData;
243
244
// 像素映射图
245
vector<PixMap> mPixMapData;
246
247
// 材质模板, 存储顺序:第一层,第一层光照图,第二层,第二层光照图
248
vector<String> mTemplateData;
249
250
// 雾
251
vector<String> mFogReplacementData;
252
253
// 手动生成的材质
254
vector<String> mManualMatData;
255
256
// 地面实体(比如桥)的碰撞面数据
257
vector<Vector3> mWCollisionData;
258
259
// 手动生成的mesh
260
vector<String> mManualMeshData;
261
262
// WCollision
263
vector<Entity*> mWCollisionEntData;
264
265
// 地形文件名字
266
String mFileName;
267
};
268

/**//*2
**************************************************************************************************************3
@fileName Terrain.h 4
@remarks 用来创建地形,和保存地形相关信息5
@author LYN 2009.10.16
***************************************************************************************************************7
*/8
#pragma once9

10
#include "TLBB.h"11
#include <vector>12
using namespace Ogre;13
using std::vector;14

15
const uint TERRAIN_QUERY_MASK = 0x00000001; // 地形查询掩码16
const unsigned short MAIN_BINDING = 0; // 主绑定17

18

/**//* 网格操作标志的枚举*/19
enum Operate20


{21
FLIP_HORIZINTAL = 1, // 图片水平翻转,即左右翻转22
FLIP_VERTICAL = 2, // 图片垂直翻转,即上下翻转23
ANTICLOCKWISE_90 = 4, // 逆时针旋转90度24
FLIP_DIAGONAL = 8 // 三角形的对角线镜像,IndexOrder==0时就把左上的纹理坐标复制到右下,否则右上到左下25
};26

27

/**//* 像素图信息28
@remarks 保存的是每个网格的纹理图片ID和纹理坐标29
*/30
struct PixMap31


{32
int textureId; 33
Real left;34
Real top;35
Real right;36
Real bottom;37
};38

39

/**//* 高度图文件头信息*/40
struct HeightMapHeader41


{42
DWORD nMagic;43
DWORD nVersion; // 版本号44
int nWidth;45
int nHeight;46
};47

48

/**//* 碰撞图文件头*/49
struct WCollisionHeader50


{51
DWORD nVersion;52
DWORD nNumber; // 三角形数量53
};54

55

/**//* 网格文件头信息*/56
struct GridHeader57


{58
DWORD nMagic;59
DWORD nVersion;60
int nWidth;61
int nHeight;62
};63

64

/**//* 单个网格类65
@remarks 1个网格就是一个正方,天龙八部的地形是根据网格信息拼接而成,但没有共享顶点,这样可以做很多层uv66
*/67
class GridInfo68


{69
public:70
// 第一层pixelmap的索引, 如果是7字节版本,读取后需交换高8位与低8位的值,71
// 需做如下操作 nFirstLayer = (nFirstLayer<<8)|(nFirstLayer>>8)72
short nFirstLayer;73

74
// 对nFirstLayer的操作, 取值是上面几个定义的宏, 可以互相组合75
BYTE nFirstLayerOp;76

77
// 第二层pixelmap的索引, 天龙八部的地表不算光照图有两层UV来融合78
short nSecondLayer;79

80
// 对nSecondLayer的操作,取值同nFirstLayerOp81
BYTE nSecondLayerOp;82

83
// 对格子的三角形的操作,可能取值如下, 0正常三角形索引, 1不同于正常的三角形索引84
BYTE IndexOrder;85
};86

87

/**//* TLBBTerrain类88
@remarks 用来生成地形89
*/90
class TLBBTerrain91


{92
public:93

/**//* 构造函数94
@param filename 地形文件名95
@param sceneMgr 场景管理器96
*/97
TLBBTerrain(const String& filename, SceneManager* sceneMgr);98
~TLBBTerrain(void);99

100

/**//* 生成地形101
@remarks 生成地形,直接调用此方法直接可以生成地形.102
*/103
void createTerrain(void);104

105

/**//* 获得地图X方向的缩放*/106
int getScaleX(void) const;107

108

/**//* 获得地图Y方向的缩放*/109
int getScaleY(void) const;110

111

/**//* 获得地图Z方向的缩放*/112
int getScaleZ(void) const;113

114

/**//* 获得地图X方向的大小*/115
int getXSize(void) const;116

117

/**//* 获得地图Z方向的大小*/118
int getZSize(void) const;119

120

/**//* 获得地图中心点*/121
const Vector3& getCentre(void) const;122

123

/**//* 获得高度图数据*/124
const vector<Real>& getHeightMapData(void) const;125

126

/**//* 获得手工材质的名字数组127
@remarks 手动生成的材质换图的时候需要手工清除,所以保留他们的名字128
*/129
const vector<String>& getManualMatData(void) const;130

131

/**//* 获得手工mesh的名字数组132
@remarks 手动生成的mesh换图的时候需要手工清除,所以保留他们的名字133
*/134
const vector<String>& getManualMeshData(void) const;135

136

/**//* 获得WCollision实体指针数组*/137
const vector<Entity*>& getmWCollisionEntData(void) const;138

139
protected:140

141

/**//* 打开网格文件142
@remarks 二进制流载入143
@param filename 网格文件名144
@param groupName 资源组名字145
*/146
void openGridFile(const String& fileName, const String &groupName);147

148

/**//* 打开高度图文件149
@remarks 二进制流载入150
@param filename 高度图文件名151
@param groupName 资源组名字152
*/153
void openHeightMapFile(const String &fileName, const String &groupName);154

155

/**//* 翻转纹理图片156
@remarks 对纹理图片的操作157
*/158
void flipPicture(int op, Vector2& TL, Vector2& TR, Vector2& BL, Vector2& BR, int indexOrder);159

160

/**//* 查找此网格的材质是否已经生成了161
@remarks 如果存在就不用再生成162
@param gridinfo 资源组名字163
@param endIndex 结束的索引,控制查询范围164
@return 如果已经生成了,就返回含有此材质的那个网格的索引, 否则返回-1165
*/166
int findSameMaterial(GridInfo& gridinfo, int endIndex); 167

168

/**//* 手工生成材质169
@remarks 克隆材质模板,再更改纹理别名即可170
*/171
void createManualMat(void); 172

173

/**//* 获得顶点法线174
@remarks 为了简单,只获得网格法线,暂时没有求顶点法线,如果要想效果更好,求平均即可得到顶点法线175
@param x 顶点缩放后的x坐标176
@param z 顶点缩放后的z坐标177
@return 法线坐标178
*/179
Vector3 getNormalAt(Real x, Real z) const; 180

181

/**//* 生成地形tile182
@remarks 直接操作硬件缓存生成地形mesh183
@param startx 没有缩放的x起点坐标184
@param startz 没有缩放的z起点坐标185
@param tileSizeX tile X方向的大小, 虽然天龙的tilesize都是32,但有的图不是tile整数倍,可以更改此值生成随意大小的tile,186
@param tileSizeZ tile Z方向的大小187
@param matName 材质名字188
*/189
bool createTileMesh(size_t startx, size_t startz, int tileSizeX, int tileSizeZ, const String& matName);190

191

/**//* 生成地形tile192
@remarks 用manualObject来做地形, 简单很多,经过测试和操作硬件缓存效率基本差不多,可以二选其一193
@param startx 没有缩放的x起点坐标194
@param startz 没有缩放的z起点坐标195
@param tileSizeX tile X方向的大小, 虽然天龙的tilesize都是32,但有的图不是tile整数倍,可以更改此值生成随意大小的tile,196
@param tileSizeZ tile Z方向的大小197
@param matName 材质名字198
*/199
void createTileManualObject(size_t startx, size_t startz, int tileSizeX, int tileSizeZ, const String& matName);200

201

/**//* 生成WCollision202
@remarks WCollision用来地形查询用,不用渲染出来,所以应该按区域分开生成多个WCollision,以减少查询的顶点数量203
@param fileName WCollision文件的名字204
@param groupName 资源组205
*/206
void createWCollision(const String &fileName , const String &groupName); 207

208
protected:209

210
// 场景管理器211
SceneManager* mSceneMgr;212

213
// 地图分块大小214
int mTileSize;215

216
// 地图大小和缩放217
int mXSize;218
int mZSize;219
int mScaleX;220
int mScaleY;221
int mScaleZ;222

223
// 地图中心点位置224
Vector3 mCentre;225

226
// 是否有光照图227
bool mHasLightMap;228

229
// 光照图文件名230
String mLightMapName;231

232
// 材质数量233
size_t mMaterialNum; 234

235
// 高度图236
vector<Real> mHeightMapData; 237

238
// 网格信息239
vector<GridInfo> mGridData; 240

241
// 纹理242
vector<String> mTextureData; 243

244
// 像素映射图245
vector<PixMap> mPixMapData; 246

247
// 材质模板, 存储顺序:第一层,第一层光照图,第二层,第二层光照图248
vector<String> mTemplateData; 249
250
// 雾251
vector<String> mFogReplacementData; 252
253
// 手动生成的材质254
vector<String> mManualMatData; 255

256
// 地面实体(比如桥)的碰撞面数据257
vector<Vector3> mWCollisionData; 258

259
// 手动生成的mesh260
vector<String> mManualMeshData; 261

262
// WCollision263
vector<Entity*> mWCollisionEntData;264

265
// 地形文件名字266
String mFileName;267
};268

源文件部分重要代码:
1
//--------------------------------------------------------------------------------------------------------
2
int TLBBTerrain::findSameMaterial(GridInfo& gridinfo, int endIndex)
3

{
4
// 网格比较
5
for (int i = 0; i < endIndex; ++ i)
6
{
7
8
if (mGridData[i].nFirstLayer < 0 )
9
{
10
continue;
11
}
12
13
// 如果有第一层
14
if (gridinfo.nFirstLayer >= 0)
15
{
16
// 第一层的纹理图片相同
17
if (mPixMapData[gridinfo.nFirstLayer].textureId == mPixMapData[mGridData[i].nFirstLayer].textureId)
18
{
19
// 如果有第二层
20
if (gridinfo.nSecondLayer >= 0)
21
{
22
if (mGridData[i].nSecondLayer >= 0)
23
{
24
// 第二层的纹理图片相同
25
if (mPixMapData[gridinfo.nSecondLayer].textureId == mPixMapData[mGridData[i].nSecondLayer].textureId)
26
{
27
return i; // 一,二层的纹理图片都相同
28
}
29
}
30
}
31
else if (mGridData[i].nSecondLayer < 0)
32
{
33
return i; // 第一层的纹理图片相同
34
}
35
}
36
}
37
else
38
{
39
// 如果第一层都没有纹理图片
.用第0个网格的材质代替,不清楚为什么会没有纹理
40
// 可能天龙有其他材质代替吧
41
return 0;
42
}
43
}
44
return -1; // 没有找到相同材质
45
}
46
47
//--------------------------------------------------------------------------------------------------------
48
void TLBBTerrain::createManualMat(void)
49

{
50
// 先获得材质模板
51
MaterialPtr materialTemplate1 = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(mTemplateData[1]));
52
MaterialPtr materialTemplate2 = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(mTemplateData[3]));
53
54
int tempIndex = -1;
55
for (int i = 0; i < mXSize*mZSize; ++ i)
56
{
57
// 如果此材质已经存在
58
if ((tempIndex = findSameMaterial(mGridData[i], i)) >= 0)
59
{
60
// 用已有材质存入数组
61
mManualMatData.push_back(mManualMatData[tempIndex]);
62
}
63
else
64
{
65
// 有第二层
66
if (mGridData[i].nSecondLayer >= 0 && mGridData[i].nFirstLayer >= 0)
67
{
68
// 拷贝第二层材质
69
String newMaterialName = "material"+StringConverter::toString(mMaterialNum); // 材质名字
70
MaterialPtr newMaterial = materialTemplate2->clone(newMaterialName); // 克隆材质
71
AliasTextureNamePairList aliasList; // 存储纹理别名的二叉树
72
String textureName1 = mTextureData[mPixMapData[mGridData[i].nFirstLayer].textureId];
73
String textureName2 = mTextureData[mPixMapData[mGridData[i].nSecondLayer].textureId];
74
aliasList["<layer0>"] = textureName1;
75
aliasList["<layer1>"] = textureName2;
76
if (mHasLightMap)
77
{
78
aliasList["<lightmap>"] = mLightMapName;
79
}
80
newMaterial->applyTextureAliases(aliasList); // 用纹理别名更改纹理
81
mManualMatData.push_back(newMaterialName); // 存入材质数组
82
}
83
else if (mGridData[i].nFirstLayer >= 0)
84
{
85
// 拷贝第一层材质
86
String newMaterialName = "material"+StringConverter::toString(mMaterialNum); // 材质名字
87
MaterialPtr newMaterial = materialTemplate1->clone(newMaterialName); // 克隆材质
88
AliasTextureNamePairList aliasList; // 存储纹理别名的二叉树
89
String textureName1 = mTextureData[mPixMapData[mGridData[i].nFirstLayer].textureId];
90
aliasList["<layer0>"] = textureName1;
91
if (mHasLightMap)
92
{
93
aliasList["<lightmap>"] = mLightMapName;
94
}
95
newMaterial->applyTextureAliases(aliasList); // 用纹理别名更改纹理
96
mManualMatData.push_back(newMaterialName); // 存入材质数组
97
98
99
}
100
101
++ mMaterialNum;
102
103
}
104
}
105
}
106
107
//--------------------------------------------------------------------------------------------------------
108
Vector3 TLBBTerrain::getNormalAt(Real x, Real z) const
109

{
110
int flip = 1;
111
int index = x + z*(mXSize+1);
112
Vector3 here(x, mHeightMapData[index], z);
113
Vector3 right;
114
Vector3 down;
115
// 边界
116
if (x >= mXSize)
117
{
118
flip *= -1;
119
right = Vector3(x-1, mHeightMapData[index-1], z);
120
}
121
else
122
{
123
right = Vector3(x+1, mHeightMapData[index+1], z);
124
}
125
126
if (z >= mZSize)
127
{
128
flip *= -1;
129
down = Vector3(x, mHeightMapData[index-mXSize-1], z-1);
130
}
131
else
132
{
133
down = Vector3(x, mHeightMapData[index+mXSize+1], z+1);
134
}
135
// 生成矢量
136
right -= here;
137
down -= here;
138
139
// 矢量正交,注意方向
140
Vector3 normal = flip * down.crossProduct(right);
141
normal.normalise(); // 归一化
142
return normal;
143
}
144
145
//--------------------------------------------------------------------------------------------------------
146
void TLBBTerrain::createTileManualObject(size_t startx, size_t startz, int tileSizeX, int tileSizeZ, const String& matName)
147

{
148
StringUtil::StrStreamType entName;
149
entName << "tile[" << startz << "]" << "[" << startx << "]" << matName;
150
151
ManualObject* mo = mSceneMgr->createManualObject(entName.str());
152
153
mo->begin(matName);
154
155
const Real width = 1;
156
int k = 0;
157
bool hasMesh = false;
158
int endx = startx + tileSizeX;
159
int endz = startz + tileSizeZ;
160
for (int z = startz; z < endz; ++ z)
161
{
162
for (int x = startx; x < endx; ++ x)
163
{
164
// 转换成一维数组索引
165
int index = x + z*mXSize;
166
// 如果存在此材质
167
if (mManualMatData[index] == matName && mGridData[index].nFirstLayer >= 0)
168
{
169
hasMesh = true;
170
171
// 高度图坐标转换
172
int heightIndex = index + z;
173
174
// 第一层纹理坐标
175
int index1 = mGridData[index].nFirstLayer;
176
Real left1 = mPixMapData[index1].left;
177
Real right1 = mPixMapData[index1].right;
178
Real top1 = mPixMapData[index1].top;
179
Real bottom1 = mPixMapData[index1].bottom;
180
Vector2 left_top_1(left1, top1);
181
Vector2 right_top_1(right1, top1);
182
Vector2 right_bottom_1(right1, bottom1);
183
Vector2 left_bottom_1(left1, bottom1);
184
// 图片翻转等操作
185
if (mGridData[index].nFirstLayerOp != 0)
186
{
187
flipPicture(mGridData[index].nFirstLayerOp, left_top_1, right_top_1,
188
left_bottom_1, right_bottom_1, mGridData[index].IndexOrder);
189
}
190
191
// 第二层纹理坐标
192
Vector2 left_top_2;
193
Vector2 right_top_2;
194
Vector2 right_bottom_2;
195
Vector2 left_bottom_2;
196
if (mGridData[index].nSecondLayer >= 0)
197
{
198
int index2 = mGridData[index].nSecondLayer;
199
Real left2 = mPixMapData[index2].left;
200
Real right2 = mPixMapData[index2].right;
201
Real top2 = mPixMapData[index2].top;
202
Real bottom2 = mPixMapData[index2].bottom;
203
left_top_2 = Vector2(left2, top2);
204
right_top_2 = Vector2(right2, top2);
205
right_bottom_2 = Vector2(right2, bottom2);
206
left_bottom_2 = Vector2(left2, bottom2);
207
if (mGridData[index].nSecondLayerOp != 0)
208
{
209
flipPicture(mGridData[index].nSecondLayerOp, left_top_2, right_top_2,
210
left_bottom_2, right_bottom_2, mGridData[index].IndexOrder);
211
}
212
213
}
214
215
// 光照图纹理坐标
216
Vector2 left_top_3;
217
Vector2 right_top_3;
218
Vector2 right_bottom_3;
219
Vector2 left_bottom_3;
220
if (mHasLightMap)
221
{
222
Real left3 = (Real)x / (Real)mXSize;
223
Real right3 = left3 + 1/(Real)mXSize;
224
Real top3 = (Real)z / (Real)mZSize;
225
Real bottom3 = top3 + 1/(Real)mZSize;
226
left_top_3 = Vector2(left3, top3);
227
right_top_3 = Vector2(right3, top3);
228
right_bottom_3 = Vector2(right3, bottom3);
229
left_bottom_3 = Vector2(left3, bottom3);
230
}
231
232
// 点0
233
mo->position(x*mScaleX, mHeightMapData[heightIndex]*mScaleY, z*mScaleZ);
234
mo->normal(getNormalAt(x, z));
235
mo->textureCoord(left_top_1);
236
if (mGridData[index].nSecondLayer >= 0)
237
{
238
mo->textureCoord(left_top_2);
239
}
240
if (mHasLightMap)
241
{
242
mo->textureCoord(left_top_3); // 光照图纹理坐标
243
}
244
245
// 点1
246
mo->position((x+width)*mScaleX, mHeightMapData[heightIndex+1]*mScaleY, z*mScaleZ);
247
mo->normal(getNormalAt(x+width, z));
248
mo->textureCoord(right_top_1);
249
if (mGridData[index].nSecondLayer >= 0)
250
{
251
mo->textureCoord(right_top_2);
252
}
253
if (mHasLightMap)
254
{
255
mo->textureCoord(right_top_3); // 光照图纹理坐标
256
}
257
258
// 点2
259
mo->position((x+width)*mScaleX, mHeightMapData[heightIndex+mXSize+2]*mScaleY, (width+z)*mScaleZ);
260
mo->normal(getNormalAt(x+width, z+width));
261
mo->textureCoord(right_bottom_1);
262
if (mGridData[index].nSecondLayer >= 0)
263
{
264
mo->textureCoord(right_bottom_2);
265
}
266
if (mHasLightMap)
267
{
268
mo->textureCoord(right_bottom_3); // 光照图纹理坐标
269
}
270
271
272
// 点3
273
mo->position(x*mScaleX, mHeightMapData[heightIndex+mXSize+1]*mScaleY, (width+z)*mScaleZ);
274
mo->normal(getNormalAt(x, z+width));
275
mo->textureCoord(left_bottom_1);
276
if (mGridData[index].nSecondLayer >= 0)
277
{
278
mo->textureCoord(left_bottom_2);
279
}
280
if (mHasLightMap)
281
{
282
mo->textureCoord(left_bottom_3); // 光照图纹理坐标
283
}
284
285
// 三角形索引顺序
286
int offset = k * 4;
287
if (mGridData[index].IndexOrder == 0)
288
{ // 正常顺序
289
mo->triangle(offset+1, offset, offset+3);
290
mo->triangle(offset+1, offset+3, offset+2);
291
}
292
else
293
{
294
mo->triangle(offset, offset+3, offset+2);
295
mo->triangle(offset, offset+2, offset+1);
296
}
297
298
++ k;
299
}
300
}
301
}
302
303
mo->end();
304
305
// 此tile含有数据才生成
306
if (hasMesh)
307
{
308
mSceneMgr->getRootSceneNode()->createChildSceneNode(mCentre)->attachObject(mo);
309
mo->setCastShadows(false);
310
mo->setQueryFlags(TERRAIN_QUERY_MASK);
311
}
312
else
313
{
314
mSceneMgr->destroyManualObject(entName.str());
315
}
316
}
317
318
//--------------------------------------------------------------------------------------------------------
319
bool TLBBTerrain::createTileMesh(size_t startx, size_t startz, int tileSizeX, int tileSizeZ, const String& matName)
320

{
321
const Real width = 1;
322
int k = 0;
323
bool hasMesh = false;
324
int endx = startx + tileSizeX;
325
int endz = startz + tileSizeZ;
326
327
// 先获得mesh顶点的数量
328
size_t vCount = 0;
329
bool hasSecondLayer = false;
330
for (int z = startz; z < endz; ++ z)
331
{
332
for (int x = startx; x < endx; ++ x)
333
{
334
int index = x + z*mXSize; // 转换成一维数组索引
335
336
//
337
if (mManualMatData[index] == matName && mGridData[index].nFirstLayer >= 0)
338
{
339
vCount += 4;
340
341
// 此材质是否有第二层
342
if (!hasSecondLayer)
343
{
344
if (mGridData[index].nSecondLayer >= 0)
345
{
346
hasSecondLayer = true;
347
}
348
}
349
}
350
}
351
}
352
353
if (vCount == 0)
354
{
355
return false;
356
}
357
358
// 生成mesh
359
StringUtil::StrStreamType meshName;
360
meshName << "gridMesh[" << startz << "]" << "[" << startx << "]" << matName;
361
MeshPtr mesh = MeshManager::getSingleton().createManual(meshName.str(), "TLBB");
362
mManualMeshData.push_back(meshName.str());
363
364
// 子mesh
365
SubMesh* sm = mesh->createSubMesh();
366
sm->useSharedVertices = false; // 不使用共享顶点
367
sm->vertexData = new VertexData();
368
sm->vertexData->vertexCount = vCount;
369
370
// 顶点结构描述
371
VertexDeclaration* decl = sm->vertexData->vertexDeclaration;
372
size_t offset = 0;
373
// 顶点位置
374
decl->addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_POSITION);
375
offset += VertexElement::getTypeSize(VET_FLOAT3);
376
// 法线
377
decl->addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_NORMAL);
378
offset += VertexElement::getTypeSize(VET_FLOAT3);
379
// 纹理坐标
380
decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
381
offset += VertexElement::getTypeSize(VET_FLOAT2);
382
if (hasSecondLayer) // 如果有第二层
383
{
384
decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1);
385
offset += VertexElement::getTypeSize(VET_FLOAT2);
386
if (mHasLightMap)
387
{
388
decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 2);
389
offset += VertexElement::getTypeSize(VET_FLOAT2);
390
}
391
}
392
else
393
{
394
if (mHasLightMap)
395
{
396
decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1);
397
offset += VertexElement::getTypeSize(VET_FLOAT2);
398
}
399
}
400
401
// 顶点缓存
402
HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton()
403
.createVertexBuffer(offset, vCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
404
// 获得顶点缓存的地址
405
float* pReal = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
406
407
// 索引缓存
408
sm->indexData->indexCount = (vCount/2)*3;
409
sm->indexData->indexBuffer = HardwareBufferManager::getSingleton()
410
.createIndexBuffer(HardwareIndexBuffer::IT_16BIT, (vCount/2)*3, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
411
// 获得索引缓存的地址
412
unsigned short* pI = static_cast<unsigned short*>(sm->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
413
414
// 循环写入数据到硬件缓存
415
AxisAlignedBox meshBounds; // AABB绑定盒
416
Real meshRadius = 0; // 球体半径
417
for (int z = startz; z < endz; ++ z)
418
{
419
for (int x = startx; x < endx; ++ x)
420
{
421
int index = x + z*mXSize; // 转换成一维数组索引
422
423
//
424
if (mManualMatData[index] == matName && mGridData[index].nFirstLayer >= 0)
425
{
426
// 高度图坐标转换
427
// 因为网格数量是192*192的话,顶点就是193*193
428
int heightIndex = index + z;
429
430
// 第一层纹理坐标
431
int index1 = mGridData[index].nFirstLayer;
432
Real left1 = mPixMapData[index1].left;
433
Real right1 = mPixMapData[index1].right;
434
Real top1 = mPixMapData[index1].top;
435
Real bottom1 = mPixMapData[index1].bottom;
436
Vector2 left_top_1(left1, top1);
437
Vector2 right_top_1(right1, top1);
438
Vector2 right_bottom_1(right1, bottom1);
439
Vector2 left_bottom_1(left1, bottom1);
440
// 图片翻转等操作
441
if (mGridData[index].nFirstLayerOp != 0)
442
{
443
flipPicture(mGridData[index].nFirstLayerOp, left_top_1, right_top_1, left_bottom_1, right_bottom_1, mGridData[index].IndexOrder);
444
}
445
446
// 第二层纹理坐标
447
Vector2 left_top_2;
448
Vector2 right_top_2;
449
Vector2 right_bottom_2;
450
Vector2 left_bottom_2;
451
if (mGridData[index].nSecondLayer >= 0)
452
{
453
int index2 = mGridData[index].nSecondLayer;
454
Real left2 = mPixMapData[index2].left;
455
Real right2 = mPixMapData[index2].right;
456
Real top2 = mPixMapData[index2].top;
457
Real bottom2 = mPixMapData[index2].bottom;
458
left_top_2 = Vector2(left2, top2);
459
right_top_2 = Vector2(right2, top2);
460
right_bottom_2 = Vector2(right2, bottom2);
461
left_bottom_2 = Vector2(left2, bottom2);
462
if (mGridData[index].nSecondLayerOp != 0)
463
{
464
flipPicture(mGridData[index].nSecondLayerOp, left_top_2, right_top_2, left_bottom_2, right_bottom_2, mGridData[index].IndexOrder);
465
}
466
}
467
468
// 光照图纹理坐标
469
Vector2 left_top_3;
470
Vector2 right_top_3;
471
Vector2 right_bottom_3;
472
Vector2 left_bottom_3;
473
if (mHasLightMap)
474
{
475
Real left3 = (Real)x / (Real)mXSize;
476
Real right3 = left3 + 1/(Real)mXSize;
477
Real top3 = (Real)z / (Real)mZSize;
478
Real bottom3 = top3 + 1/(Real)mZSize;
479
left_top_3 = Vector2(left3, top3);
480
right_top_3 = Vector2(right3, top3);
481
right_bottom_3 = Vector2(right3, bottom3);
482
left_bottom_3 = Vector2(left3, bottom3);
483
}
484
485
// 对mesh每个网格的个顶点编写数据
486
// 点0
487
// position
488
Vector3 position(x*mScaleX, mHeightMapData[heightIndex]*mScaleY, z*mScaleZ);
489
*pReal++ = position.x;
490
*pReal++ = position.y;
491
*pReal++ = position.z;
492
meshBounds.merge(position); // update bounds
493
meshRadius = std::max(meshRadius, position.length()); // update bounds
494
// normal
495
Vector3 normal = getNormalAt(x, z);
496
*pReal++ = normal.x;
497
*pReal++ = normal.y;
498
*pReal++ = normal.z;
499
// uv1
500
*pReal++ = left_top_1.x;
501
*pReal++ = left_top_1.y;
502
// uv2
503
if (mGridData[index].nSecondLayer >= 0)
504
{
505
*pReal++ = left_top_2.x;
506
*pReal++ = left_top_2.y;
507
}
508
// uv3
509
if (mHasLightMap)
510
{
511
*pReal++ = left_top_3.x;
512
*pReal++ = left_top_3.y;
513
}
514
515
516
// 点1
517
// position
518
position = Vector3((x+width)*mScaleX, mHeightMapData[heightIndex+1]*mScaleY, z*mScaleZ);
519
*pReal++ = position.x;
520
*pReal++ = position.y;
521
*pReal++ = position.z;
522
meshBounds.merge(position); // update bounds
523
meshRadius = std::max(meshRadius, position.length()); // update bounds
524
// normal
525
normal = getNormalAt(x+width, z);
526
*pReal++ = normal.x;
527
*pReal++ = normal.y;
528
*pReal++ = normal.z;
529
// uv1
530
*pReal++ = right_top_1.x;
531
*pReal++ = right_top_1.y;
532
// uv2
533
if (mGridData[index].nSecondLayer >= 0)
534
{
535
*pReal++ = right_top_2.x;
536
*pReal++ = right_top_2.y;
537
}
538
// uv3
539
if (mHasLightMap)
540
{
541
*pReal++ = right_top_3.x;
542
*pReal++ = right_top_3.y;
543
}
544
545
// 点2
546
// position
547
position = Vector3((x+width)*mScaleX, mHeightMapData[heightIndex+mXSize+2]*mScaleY, (z+width)*mScaleZ);
548
*pReal++ = position.x;
549
*pReal++ = position.y;
550
*pReal++ = position.z;
551
meshBounds.merge(position); // update bounds
552
meshRadius = std::max(meshRadius, position.length()); // update bounds
553
// normal
554
normal = getNormalAt(x+width, z+width);
555
*pReal++ = normal.x;
556
*pReal++ = normal.y;
557
*pReal++ = normal.z;
558
// uv1
559
*pReal++ = right_bottom_1.x;
560
*pReal++ = right_bottom_1.y;
561
// uv2
562
if (mGridData[index].nSecondLayer >= 0)
563
{
564
*pReal++ = right_bottom_2.x;
565
*pReal++ = right_bottom_2.y;
566
}
567
// uv3
568
if (mHasLightMap)
569
{
570
*pReal++ = right_bottom_3.x;
571
*pReal++ = right_bottom_3.y;
572
}
573
574
// 点3
575
// position
576
position = Vector3(x*mScaleX, mHeightMapData[heightIndex+mXSize+1]*mScaleY, (z+width)*mScaleZ);
577
*pReal++ = position.x;
578
*pReal++ = position.y;
579
*pReal++ = position.z;
580
meshBounds.merge(position); // update bounds
581
meshRadius = std::max(meshRadius, position.length()); // update bounds
582
// normal
583
normal = getNormalAt(x, z+width);
584
*pReal++ = normal.x;
585
*pReal++ = normal.y;
586
*pReal++ = normal.z;
587
// uv1
588
*pReal++ = left_bottom_1.x;
589
*pReal++ = left_bottom_1.y;
590
// uv2
591
if (mGridData[index].nSecondLayer >= 0)
592
{
593
*pReal++ = left_bottom_2.x;
594
*pReal++ = left_bottom_2.y;
595
}
596
// uv3
597
if (mHasLightMap)
598
{
599
*pReal++ = left_bottom_3.x;
600
*pReal++ = left_bottom_3.y;
601
}
602
603
// 索引
604
int off = k * 4;
605
if (mGridData[index].IndexOrder == 0) // 正常索引顺序
606
{
607
*pI++ = 1 + off;
608
*pI++ = 0 + off;
609
*pI++ = 3 + off;
610
611
*pI++ = 1 + off;
612
*pI++ = 3 + off;
613
*pI++ = 2 + off;
614
}
615
else
616
{
617
*pI++ = 0 + off;
618
*pI++ = 3 + off;
619
*pI++ = 2 + off;
620
621
*pI++ = 0 + off;
622
*pI++ = 2 + off;
623
*pI++ = 1 + off;
624
}
625
626
++ k;
627
}
628
}
629
}
630
631
vbuf->unlock();
632
sm->vertexData->vertexBufferBinding->setBinding(MAIN_BINDING, vbuf); // 绑定顶点缓存
633
634
sm->indexData->indexBuffer->unlock();
635
636
sm->setMaterialName(matName);
637
638
// 设置绑定盒子和球体半径, 查询裁剪用
639
//Real min = -10*mScaleY;
640
//Real max = 25*mScaleY;
641
//AxisAlignedBox meshBounds(
642
// (Real)startx*mScaleX,
643
// min,
644
// (Real)startz*mScaleZ,
645
// (Real)(endx - 1)*mScaleX,
646
// max,
647
// (Real)(endz - 1)*mScaleZ);
648
649
//Real meshRadius = Math::Sqrt(
650
// Math::Sqr(max - min) +
651
// Math::Sqr((endx - 1 - startx) * mScaleX) +
652
// Math::Sqr((endz - 1 - startz) * mScaleZ)) / 2;
653
654
mesh->_setBounds(meshBounds);
655
mesh->_setBoundingSphereRadius(meshRadius);
656
657
mesh->load();
658
659
return true;
660
}
661
662
//--------------------------------------------------------------------------------------------------------
663
void TLBBTerrain::createWCollision(const String &fileName , const String &groupName)
664

{
665
DataStreamPtr stream = ResourceGroupManager::getSingleton().openResource(fileName , groupName);
666
667
// 读取文件头, 8个字节的结构
668
WCollisionHeader header;
669
stream->read(&header , sizeof(header));
670
671
Vector3 vec3 = Vector3::ZERO;
672
int col = 0;
673
int row = 0;
674
int preCol = 0; // 前一个数据块的列
675
int preRow = 0; // 前一个数据块的行
676
int number = 0;
677
int k = 0;
678
bool firstTime = true; // 第一次
679
680
while (!stream->eof())
681
{
682
// 行列坐标, 决定WCollision的分块信息的
683
// 如果把WCOliision做成一个mesh,每次都会全部查询,效率很低
684
stream->read(&col, sizeof(row));
685
stream->read(&row, sizeof(col));
686
687
stream->read(&number, sizeof(number)); // 数据块的三角形数量
688
689
// 读取此数据块的三角形顶点数据
690
for (int i = 0; i < number * 3; ++ i)
691
{
692
stream->read(&vec3, sizeof(vec3));
693
mWCollisionData.push_back(vec3);
694
}
695
696
if (mWCollisionData.size() == 0)
697
{
698
break;
699
}
700
701
// 初始化
702
if (firstTime)
703
{
704
preCol = col;
705
preRow = row;
706
firstTime = false;
707
}
708
709
// 行列坐标相连,就做成一个mesh
710
if (col == preCol && (row - preRow) <= 1)
711
{
712
preCol = col;
713
preRow = row;
714
}
715
else
716
{
717
// 生成
718
ManualObject mo("mo");
719
mo.begin("", RenderOperation::OT_TRIANGLE_LIST);
720
for(size_t i = 0; i < mWCollisionData.size(); i += 3)
721
{
722
// 点1
723
mo.position(mWCollisionData[i].x*mScaleX, mWCollisionData[i].y*mScaleY, mWCollisionData[i].z*mScaleZ);
724
mo.colour(ColourValue(0, 0, 1));
725
726
// 点2
727
mo.position(mWCollisionData[i+1].x*mScaleX, mWCollisionData[i+1].y*mScaleY, mWCollisionData[i+1].z*mScaleZ);
728
mo.colour(ColourValue(0, 0, 1));
729
730
// 点3
731
mo.position(mWCollisionData[i+2].x*mScaleX, mWCollisionData[i+2].y*mScaleY, mWCollisionData[i+2].z*mScaleZ);
732
mo.colour(ColourValue(0, 0, 1));
733
734
// 三角形索引顺序
735
mo.triangle(i, i+1, i+2);
736
}
737
mo.end();
738
739
String meshName = "WCollisionMesh"+StringConverter::toString(k);
740
mo.convertToMesh(meshName, "TLBB");
741
mManualMeshData.push_back(meshName);
742
743
Entity* ent = mSceneMgr->createEntity("WCollison"+StringConverter::toString(k), meshName);
744
mWCollisionEntData.push_back(ent); //
745
ent->setCastShadows(false);
746
ent->setQueryFlags(TERRAIN_QUERY_MASK);
747
748
SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode(mCentre);
749
node->attachObject(ent);
750
751
mWCollisionData.clear(); //
752
firstTime = true;
753
++ k;
754
}
755
} // end of while
756
}
757
758
//--------------------------------------------------------------------------------------------------------
759
void TLBBTerrain::createTerrain()
760

{
761
// 生成材质
762
LogManager::getSingleton().logMessage(LML_CRITICAL, "开始生成材质
");
763
createManualMat();
764
765
// 生成WCollision
766
LogManager::getSingleton().logMessage(LML_CRITICAL, "开始生成WCollsion
");
767
vector<String> vec;
768
vec = StringUtil::split(mFileName, ".", 1);
769
String tempStr = vec[0] + ".WCollision";
770
createWCollision(tempStr, "TLBB");
771
772
// 地形mesh
773
LogManager::getSingleton().logMessage(LML_CRITICAL, "开始生成地形mesh
");
774
775
// 判断地形大小是否能被tile整除,不能整除就需要矫正每行每列最后一个tile的大小
776
// 在循环外部判断,就不用每次循环都判断,效率更高
777
if (mXSize % mTileSize != 0 || mZSize % mTileSize != 0)
778
{
779
for (size_t matIndex = 0; matIndex < mMaterialNum; ++ matIndex)
780
{
781
// 材质名字
782
// toString和StrStreamType是用std::ostringstream来做的,非常消耗cpu,尽量减少循环数次
783
// 或者用sprintf来做
784
String matName = "material" + StringConverter::toString(matIndex);
785
786
// 同材质的mesh按tile区域生成
787
for (size_t i = 0; i < mZSize; i += mTileSize)
788
{
789
for (size_t j = 0; j < mXSize; j += mTileSize)
790
{
791
// 矫正tile大小
792
int tielSizeZ = mTileSize;
793
int tileSizeX = mTileSize;
794
if (mZSize - i < mTileSize)
795
{
796
tielSizeZ = mZSize - i;
797
}
798
if (mXSize - j < mTileSize)
799
{
800
tileSizeX = mXSize - j;
801
}
802
803
// 第一种方法
804
// 现有的地形检测暂时不支持ManualObject,以后考虑添加
805
//createTileManualObject(j, i, tileSizeX, tielSizeZ, matName);
806
807
// 第二种方法
808
if (createTileMesh(j, i, tileSizeX, tielSizeZ, matName))
809
{
810
StringUtil::StrStreamType entName;
811
StringUtil::StrStreamType meshName;
812
entName << "tile[" << i << "]" << "[" << j << "]" << matName;
813
meshName << "gridMesh[" << i << "]" << "[" << j << "]" << matName;
814
Entity* entity = mSceneMgr->createEntity(entName.str(), meshName.str());
815
entity->setCastShadows(false);
816
entity->setQueryFlags(TERRAIN_QUERY_MASK);
817
mSceneMgr->getRootSceneNode()->createChildSceneNode(mCentre)->attachObject(entity);
818
}
819
}
820
}
821
}
822
}
823
else
824
{
825
for (size_t matIndex = 0; matIndex < mMaterialNum; ++ matIndex)
826
{
827
// 材质名字
828
// toString和StrStreamType是用std::ostringstream来做的,非常消耗cpu,尽量减少循环数次
829
// 或者用sprintf来做
830
String matName = "material" + StringConverter::toString(matIndex);
831
832
// 同材质的mesh按tile区域生成
833
for (size_t i = 0; i < mZSize; i += mTileSize)
834
{
835
for (size_t j = 0; j < mXSize; j += mTileSize)
836
{
837
838
// 第一种方法
839
// 现有的地形检测暂时不支持ManualObject,以后考虑添加
840
//createTileManualObject(j, i, mTileSize, mTileSize, matName);
841
842
// 第二种方法
843
if (createTileMesh(j, i, mTileSize, mTileSize, matName))
844
{
845
StringUtil::StrStreamType entName;
846
StringUtil::StrStreamType meshName;
847
entName << "tile[" << i << "]" << "[" << j << "]" << matName;
848
meshName << "gridMesh[" << i << "]" << "[" << j << "]" << matName;
849
Entity* entity = mSceneMgr->createEntity(entName.str(), meshName.str());
850
entity->setCastShadows(false);
851
entity->setQueryFlags(TERRAIN_QUERY_MASK);
852
mSceneMgr->getRootSceneNode()->createChildSceneNode(mCentre)->attachObject(entity);
853
}
854
}
855
}
856
}
857
}
858
}
//--------------------------------------------------------------------------------------------------------2
int TLBBTerrain::findSameMaterial(GridInfo& gridinfo, int endIndex)3


{4
// 网格比较5
for (int i = 0; i < endIndex; ++ i)6

{7

8
if (mGridData[i].nFirstLayer < 0 )9

{10
continue;11
}12

13
// 如果有第一层14
if (gridinfo.nFirstLayer >= 0)15

{16
// 第一层的纹理图片相同17
if (mPixMapData[gridinfo.nFirstLayer].textureId == mPixMapData[mGridData[i].nFirstLayer].textureId)18

{19
// 如果有第二层20
if (gridinfo.nSecondLayer >= 0)21

{22
if (mGridData[i].nSecondLayer >= 0)23

{ 24
// 第二层的纹理图片相同25
if (mPixMapData[gridinfo.nSecondLayer].textureId == mPixMapData[mGridData[i].nSecondLayer].textureId)26

{27
return i; // 一,二层的纹理图片都相同28
}29
}30
}31
else if (mGridData[i].nSecondLayer < 0)32

{ 33
return i; // 第一层的纹理图片相同34
}35
}36
}37
else38

{ 39
// 如果第一层都没有纹理图片
.用第0个网格的材质代替,不清楚为什么会没有纹理40
// 可能天龙有其他材质代替吧41
return 0;42
}43
}44
return -1; // 没有找到相同材质45
}46

47
//--------------------------------------------------------------------------------------------------------48
void TLBBTerrain::createManualMat(void)49


{50
// 先获得材质模板51
MaterialPtr materialTemplate1 = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(mTemplateData[1]));52
MaterialPtr materialTemplate2 = static_cast<MaterialPtr>(MaterialManager::getSingleton().getByName(mTemplateData[3])); 53

54
int tempIndex = -1;55
for (int i = 0; i < mXSize*mZSize; ++ i)56

{57
// 如果此材质已经存在58
if ((tempIndex = findSameMaterial(mGridData[i], i)) >= 0)59

{60
// 用已有材质存入数组61
mManualMatData.push_back(mManualMatData[tempIndex]);62
}63
else64

{ 65
// 有第二层66
if (mGridData[i].nSecondLayer >= 0 && mGridData[i].nFirstLayer >= 0)67

{ 68
// 拷贝第二层材质69
String newMaterialName = "material"+StringConverter::toString(mMaterialNum); // 材质名字70
MaterialPtr newMaterial = materialTemplate2->clone(newMaterialName); // 克隆材质 71
AliasTextureNamePairList aliasList; // 存储纹理别名的二叉树 72
String textureName1 = mTextureData[mPixMapData[mGridData[i].nFirstLayer].textureId];73
String textureName2 = mTextureData[mPixMapData[mGridData[i].nSecondLayer].textureId];74
aliasList["<layer0>"] = textureName1;75
aliasList["<layer1>"] = textureName2;76
if (mHasLightMap)77

{78
aliasList["<lightmap>"] = mLightMapName;79
}80
newMaterial->applyTextureAliases(aliasList); // 用纹理别名更改纹理 81
mManualMatData.push_back(newMaterialName); // 存入材质数组82
}83
else if (mGridData[i].nFirstLayer >= 0)84

{85
// 拷贝第一层材质86
String newMaterialName = "material"+StringConverter::toString(mMaterialNum); // 材质名字87
MaterialPtr newMaterial = materialTemplate1->clone(newMaterialName); // 克隆材质 88
AliasTextureNamePairList aliasList; // 存储纹理别名的二叉树 89
String textureName1 = mTextureData[mPixMapData[mGridData[i].nFirstLayer].textureId];90
aliasList["<layer0>"] = textureName1;91
if (mHasLightMap)92

{93
aliasList["<lightmap>"] = mLightMapName;94
}95
newMaterial->applyTextureAliases(aliasList); // 用纹理别名更改纹理 96
mManualMatData.push_back(newMaterialName); // 存入材质数组97

98
99
}100

101
++ mMaterialNum;102
103
}104
}105
}106

107
//--------------------------------------------------------------------------------------------------------108
Vector3 TLBBTerrain::getNormalAt(Real x, Real z) const109


{110
int flip = 1;111
int index = x + z*(mXSize+1);112
Vector3 here(x, mHeightMapData[index], z);113
Vector3 right;114
Vector3 down;115
// 边界116
if (x >= mXSize)117

{118
flip *= -1;119
right = Vector3(x-1, mHeightMapData[index-1], z);120
}121
else122

{123
right = Vector3(x+1, mHeightMapData[index+1], z);124
}125

126
if (z >= mZSize)127

{128
flip *= -1;129
down = Vector3(x, mHeightMapData[index-mXSize-1], z-1);130
}131
else132

{133
down = Vector3(x, mHeightMapData[index+mXSize+1], z+1);134
}135
// 生成矢量136
right -= here;137
down -= here;138

139
// 矢量正交,注意方向140
Vector3 normal = flip * down.crossProduct(right);141
normal.normalise(); // 归一化142
return normal;143
}144

145
//--------------------------------------------------------------------------------------------------------146
void TLBBTerrain::createTileManualObject(size_t startx, size_t startz, int tileSizeX, int tileSizeZ, const String& matName)147


{148
StringUtil::StrStreamType entName;149
entName << "tile[" << startz << "]" << "[" << startx << "]" << matName;150

151
ManualObject* mo = mSceneMgr->createManualObject(entName.str());152

153
mo->begin(matName);154

155
const Real width = 1;156
int k = 0;157
bool hasMesh = false;158
int endx = startx + tileSizeX;159
int endz = startz + tileSizeZ;160
for (int z = startz; z < endz; ++ z)161

{162
for (int x = startx; x < endx; ++ x)163

{164
// 转换成一维数组索引165
int index = x + z*mXSize; 166
// 如果存在此材质167
if (mManualMatData[index] == matName && mGridData[index].nFirstLayer >= 0)168

{169
hasMesh = true;170

171
// 高度图坐标转换172
int heightIndex = index + z;173

174
// 第一层纹理坐标175
int index1 = mGridData[index].nFirstLayer;176
Real left1 = mPixMapData[index1].left;177
Real right1 = mPixMapData[index1].right;178
Real top1 = mPixMapData[index1].top;179
Real bottom1 = mPixMapData[index1].bottom;180
Vector2 left_top_1(left1, top1);181
Vector2 right_top_1(right1, top1);182
Vector2 right_bottom_1(right1, bottom1);183
Vector2 left_bottom_1(left1, bottom1);184
// 图片翻转等操作185
if (mGridData[index].nFirstLayerOp != 0)186

{187
flipPicture(mGridData[index].nFirstLayerOp, left_top_1, right_top_1, 188
left_bottom_1, right_bottom_1, mGridData[index].IndexOrder);189
}190

191
// 第二层纹理坐标192
Vector2 left_top_2;193
Vector2 right_top_2;194
Vector2 right_bottom_2;195
Vector2 left_bottom_2;196
if (mGridData[index].nSecondLayer >= 0)197

{198
int index2 = mGridData[index].nSecondLayer;199
Real left2 = mPixMapData[index2].left;200
Real right2 = mPixMapData[index2].right;201
Real top2 = mPixMapData[index2].top;202
Real bottom2 = mPixMapData[index2].bottom;203
left_top_2 = Vector2(left2, top2);204
right_top_2 = Vector2(right2, top2);205
right_bottom_2 = Vector2(right2, bottom2);206
left_bottom_2 = Vector2(left2, bottom2);207
if (mGridData[index].nSecondLayerOp != 0)208

{209
flipPicture(mGridData[index].nSecondLayerOp, left_top_2, right_top_2, 210
left_bottom_2, right_bottom_2, mGridData[index].IndexOrder);211
}212
213
}214

215
// 光照图纹理坐标216
Vector2 left_top_3;217
Vector2 right_top_3;218
Vector2 right_bottom_3;219
Vector2 left_bottom_3;220
if (mHasLightMap)221

{222
Real left3 = (Real)x / (Real)mXSize; 223
Real right3 = left3 + 1/(Real)mXSize;224
Real top3 = (Real)z / (Real)mZSize;225
Real bottom3 = top3 + 1/(Real)mZSize;226
left_top_3 = Vector2(left3, top3);227
right_top_3 = Vector2(right3, top3);228
right_bottom_3 = Vector2(right3, bottom3);229
left_bottom_3 = Vector2(left3, bottom3);230
}231

232
// 点0233
mo->position(x*mScaleX, mHeightMapData[heightIndex]*mScaleY, z*mScaleZ);234
mo->normal(getNormalAt(x, z));235
mo->textureCoord(left_top_1);236
if (mGridData[index].nSecondLayer >= 0)237

{238
mo->textureCoord(left_top_2);239
}240
if (mHasLightMap)241

{242
mo->textureCoord(left_top_3); // 光照图纹理坐标243
}244

245
// 点1246
mo->position((x+width)*mScaleX, mHeightMapData[heightIndex+1]*mScaleY, z*mScaleZ);247
mo->normal(getNormalAt(x+width, z));248
mo->textureCoord(right_top_1);249
if (mGridData[index].nSecondLayer >= 0)250

{251
mo->textureCoord(right_top_2);252
}253
if (mHasLightMap)254

{255
mo->textureCoord(right_top_3); // 光照图纹理坐标256
}257

258
// 点2259
mo->position((x+width)*mScaleX, mHeightMapData[heightIndex+mXSize+2]*mScaleY, (width+z)*mScaleZ);260
mo->normal(getNormalAt(x+width, z+width));261
mo->textureCoord(right_bottom_1);262
if (mGridData[index].nSecondLayer >= 0)263

{264
mo->textureCoord(right_bottom_2);265
}266
if (mHasLightMap)267

{268
mo->textureCoord(right_bottom_3); // 光照图纹理坐标269
}270

271

272
// 点3273
mo->position(x*mScaleX, mHeightMapData[heightIndex+mXSize+1]*mScaleY, (width+z)*mScaleZ);274
mo->normal(getNormalAt(x, z+width));275
mo->textureCoord(left_bottom_1);276
if (mGridData[index].nSecondLayer >= 0)277

{278
mo->textureCoord(left_bottom_2);279
}280
if (mHasLightMap)281

{282
mo->textureCoord(left_bottom_3); // 光照图纹理坐标283
}284

285
// 三角形索引顺序286
int offset = k * 4;287
if (mGridData[index].IndexOrder == 0)288

{ // 正常顺序289
mo->triangle(offset+1, offset, offset+3);290
mo->triangle(offset+1, offset+3, offset+2);291
}292
else293

{294
mo->triangle(offset, offset+3, offset+2);295
mo->triangle(offset, offset+2, offset+1);296
}297

298
++ k;299
}300
}301
}302

303
mo->end();304

305
// 此tile含有数据才生成306
if (hasMesh)307

{308
mSceneMgr->getRootSceneNode()->createChildSceneNode(mCentre)->attachObject(mo);309
mo->setCastShadows(false);310
mo->setQueryFlags(TERRAIN_QUERY_MASK);311
}312
else313

{314
mSceneMgr->destroyManualObject(entName.str());315
}316
}317

318
//--------------------------------------------------------------------------------------------------------319
bool TLBBTerrain::createTileMesh(size_t startx, size_t startz, int tileSizeX, int tileSizeZ, const String& matName)320


{321
const Real width = 1;322
int k = 0;323
bool hasMesh = false;324
int endx = startx + tileSizeX;325
int endz = startz + tileSizeZ;326

327
// 先获得mesh顶点的数量328
size_t vCount = 0;329
bool hasSecondLayer = false;330
for (int z = startz; z < endz; ++ z)331

{332
for (int x = startx; x < endx; ++ x)333

{334
int index = x + z*mXSize; // 转换成一维数组索引335

336
// 337
if (mManualMatData[index] == matName && mGridData[index].nFirstLayer >= 0)338

{339
vCount += 4;340
341
// 此材质是否有第二层342
if (!hasSecondLayer)343

{344
if (mGridData[index].nSecondLayer >= 0)345

{346
hasSecondLayer = true;347
}348
}349
}350
}351
}352

353
if (vCount == 0)354

{355
return false;356
}357

358
// 生成mesh359
StringUtil::StrStreamType meshName;360
meshName << "gridMesh[" << startz << "]" << "[" << startx << "]" << matName;361
MeshPtr mesh = MeshManager::getSingleton().createManual(meshName.str(), "TLBB");362
mManualMeshData.push_back(meshName.str());363

364
// 子mesh365
SubMesh* sm = mesh->createSubMesh();366
sm->useSharedVertices = false; // 不使用共享顶点367
sm->vertexData = new VertexData();368
sm->vertexData->vertexCount = vCount;369

370
// 顶点结构描述371
VertexDeclaration* decl = sm->vertexData->vertexDeclaration;372
size_t offset = 0;373
// 顶点位置374
decl->addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_POSITION);375
offset += VertexElement::getTypeSize(VET_FLOAT3);376
// 法线377
decl->addElement(MAIN_BINDING, offset, VET_FLOAT3, VES_NORMAL);378
offset += VertexElement::getTypeSize(VET_FLOAT3);379
// 纹理坐标380
decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); 381
offset += VertexElement::getTypeSize(VET_FLOAT2);382
if (hasSecondLayer) // 如果有第二层383

{384
decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1);385
offset += VertexElement::getTypeSize(VET_FLOAT2);386
if (mHasLightMap)387

{388
decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 2);389
offset += VertexElement::getTypeSize(VET_FLOAT2);390
}391
}392
else393

{394
if (mHasLightMap)395

{396
decl->addElement(MAIN_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 1);397
offset += VertexElement::getTypeSize(VET_FLOAT2);398
}399
}400

401
// 顶点缓存402
HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton()403
.createVertexBuffer(offset, vCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY);404
// 获得顶点缓存的地址405
float* pReal = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));406

407
// 索引缓存408
sm->indexData->indexCount = (vCount/2)*3;409
sm->indexData->indexBuffer = HardwareBufferManager::getSingleton()410
.createIndexBuffer(HardwareIndexBuffer::IT_16BIT, (vCount/2)*3, HardwareBuffer::HBU_STATIC_WRITE_ONLY);411
// 获得索引缓存的地址412
unsigned short* pI = static_cast<unsigned short*>(sm->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));413

414
// 循环写入数据到硬件缓存415
AxisAlignedBox meshBounds; // AABB绑定盒416
Real meshRadius = 0; // 球体半径417
for (int z = startz; z < endz; ++ z)418

{419
for (int x = startx; x < endx; ++ x)420

{421
int index = x + z*mXSize; // 转换成一维数组索引422

423
// 424
if (mManualMatData[index] == matName && mGridData[index].nFirstLayer >= 0)425

{426
// 高度图坐标转换427
// 因为网格数量是192*192的话,顶点就是193*193428
int heightIndex = index + z;429

430
// 第一层纹理坐标431
int index1 = mGridData[index].nFirstLayer;432
Real left1 = mPixMapData[index1].left;433
Real right1 = mPixMapData[index1].right;434
Real top1 = mPixMapData[index1].top;435
Real bottom1 = mPixMapData[index1].bottom;436
Vector2 left_top_1(left1, top1);437
Vector2 right_top_1(right1, top1);438
Vector2 right_bottom_1(right1, bottom1);439
Vector2 left_bottom_1(left1, bottom1);440
// 图片翻转等操作441
if (mGridData[index].nFirstLayerOp != 0)442

{443
flipPicture(mGridData[index].nFirstLayerOp, left_top_1, right_top_1, left_bottom_1, right_bottom_1, mGridData[index].IndexOrder);444
}445

446
// 第二层纹理坐标447
Vector2 left_top_2;448
Vector2 right_top_2;449
Vector2 right_bottom_2;450
Vector2 left_bottom_2;451
if (mGridData[index].nSecondLayer >= 0)452

{453
int index2 = mGridData[index].nSecondLayer;454
Real left2 = mPixMapData[index2].left;455
Real right2 = mPixMapData[index2].right;456
Real top2 = mPixMapData[index2].top;457
Real bottom2 = mPixMapData[index2].bottom;458
left_top_2 = Vector2(left2, top2);459
right_top_2 = Vector2(right2, top2);460
right_bottom_2 = Vector2(right2, bottom2);461
left_bottom_2 = Vector2(left2, bottom2);462
if (mGridData[index].nSecondLayerOp != 0)463

{464
flipPicture(mGridData[index].nSecondLayerOp, left_top_2, right_top_2, left_bottom_2, right_bottom_2, mGridData[index].IndexOrder);465
}466
}467

468
// 光照图纹理坐标469
Vector2 left_top_3;470
Vector2 right_top_3;471
Vector2 right_bottom_3;472
Vector2 left_bottom_3;473
if (mHasLightMap)474

{475
Real left3 = (Real)x / (Real)mXSize; 476
Real right3 = left3 + 1/(Real)mXSize;477
Real top3 = (Real)z / (Real)mZSize;478
Real bottom3 = top3 + 1/(Real)mZSize;479
left_top_3 = Vector2(left3, top3);480
right_top_3 = Vector2(right3, top3);481
right_bottom_3 = Vector2(right3, bottom3);482
left_bottom_3 = Vector2(left3, bottom3);483
}484

485
// 对mesh每个网格的个顶点编写数据486
// 点0487
// position488
Vector3 position(x*mScaleX, mHeightMapData[heightIndex]*mScaleY, z*mScaleZ);489
*pReal++ = position.x;490
*pReal++ = position.y;491
*pReal++ = position.z;492
meshBounds.merge(position); // update bounds493
meshRadius = std::max(meshRadius, position.length()); // update bounds494
// normal495
Vector3 normal = getNormalAt(x, z);496
*pReal++ = normal.x;497
*pReal++ = normal.y;498
*pReal++ = normal.z;499
// uv1500
*pReal++ = left_top_1.x;501
*pReal++ = left_top_1.y;502
// uv2503
if (mGridData[index].nSecondLayer >= 0)504

{505
*pReal++ = left_top_2.x;506
*pReal++ = left_top_2.y;507
}508
// uv3509
if (mHasLightMap)510

{511
*pReal++ = left_top_3.x;512
*pReal++ = left_top_3.y;513
}514

515

516
// 点1517
// position518
position = Vector3((x+width)*mScaleX, mHeightMapData[heightIndex+1]*mScaleY, z*mScaleZ);519
*pReal++ = position.x;520
*pReal++ = position.y;521
*pReal++ = position.z;522
meshBounds.merge(position); // update bounds523
meshRadius = std::max(meshRadius, position.length()); // update bounds524
// normal525
normal = getNormalAt(x+width, z);526
*pReal++ = normal.x;527
*pReal++ = normal.y;528
*pReal++ = normal.z;529
// uv1530
*pReal++ = right_top_1.x;531
*pReal++ = right_top_1.y;532
// uv2533
if (mGridData[index].nSecondLayer >= 0)534

{535
*pReal++ = right_top_2.x;536
*pReal++ = right_top_2.y;537
}538
// uv3539
if (mHasLightMap)540

{541
*pReal++ = right_top_3.x;542
*pReal++ = right_top_3.y;543
}544

545
// 点2546
// position547
position = Vector3((x+width)*mScaleX, mHeightMapData[heightIndex+mXSize+2]*mScaleY, (z+width)*mScaleZ);548
*pReal++ = position.x;549
*pReal++ = position.y;550
*pReal++ = position.z;551
meshBounds.merge(position); // update bounds552
meshRadius = std::max(meshRadius, position.length()); // update bounds553
// normal554
normal = getNormalAt(x+width, z+width);555
*pReal++ = normal.x;556
*pReal++ = normal.y;557
*pReal++ = normal.z;558
// uv1559
*pReal++ = right_bottom_1.x;560
*pReal++ = right_bottom_1.y;561
// uv2562
if (mGridData[index].nSecondLayer >= 0)563

{564
*pReal++ = right_bottom_2.x;565
*pReal++ = right_bottom_2.y;566
}567
// uv3568
if (mHasLightMap)569

{570
*pReal++ = right_bottom_3.x;571
*pReal++ = right_bottom_3.y;572
}573

574
// 点3575
// position576
position = Vector3(x*mScaleX, mHeightMapData[heightIndex+mXSize+1]*mScaleY, (z+width)*mScaleZ);577
*pReal++ = position.x;578
*pReal++ = position.y;579
*pReal++ = position.z;580
meshBounds.merge(position); // update bounds581
meshRadius = std::max(meshRadius, position.length()); // update bounds582
// normal583
normal = getNormalAt(x, z+width);584
*pReal++ = normal.x;585
*pReal++ = normal.y;586
*pReal++ = normal.z;587
// uv1588
*pReal++ = left_bottom_1.x;589
*pReal++ = left_bottom_1.y;590
// uv2591
if (mGridData[index].nSecondLayer >= 0)592

{593
*pReal++ = left_bottom_2.x;594
*pReal++ = left_bottom_2.y;595
}596
// uv3597
if (mHasLightMap)598

{599
*pReal++ = left_bottom_3.x;600
*pReal++ = left_bottom_3.y;601
}602

603
// 索引604
int off = k * 4;605
if (mGridData[index].IndexOrder == 0) // 正常索引顺序606

{607
*pI++ = 1 + off;608
*pI++ = 0 + off;609
*pI++ = 3 + off;610

611
*pI++ = 1 + off;612
*pI++ = 3 + off;613
*pI++ = 2 + off;614
}615
else616

{617
*pI++ = 0 + off;618
*pI++ = 3 + off;619
*pI++ = 2 + off;620

621
*pI++ = 0 + off;622
*pI++ = 2 + off;623
*pI++ = 1 + off;624
}625

626
++ k;627
}628
}629
}630

631
vbuf->unlock();632
sm->vertexData->vertexBufferBinding->setBinding(MAIN_BINDING, vbuf); // 绑定顶点缓存633

634
sm->indexData->indexBuffer->unlock();635

636
sm->setMaterialName(matName);637

638
// 设置绑定盒子和球体半径, 查询裁剪用639
//Real min = -10*mScaleY;640
//Real max = 25*mScaleY;641
//AxisAlignedBox meshBounds(642
// (Real)startx*mScaleX, 643
// min, 644
// (Real)startz*mScaleZ,645
// (Real)(endx - 1)*mScaleX, 646
// max, 647
// (Real)(endz - 1)*mScaleZ);648

649
//Real meshRadius = Math::Sqrt(650
// Math::Sqr(max - min) +651
// Math::Sqr((endx - 1 - startx) * mScaleX) +652
// Math::Sqr((endz - 1 - startz) * mScaleZ)) / 2;653

654
mesh->_setBounds(meshBounds);655
mesh->_setBoundingSphereRadius(meshRadius);656

657
mesh->load();658

659
return true;660
}661

662
//--------------------------------------------------------------------------------------------------------663
void TLBBTerrain::createWCollision(const String &fileName , const String &groupName)664


{665
DataStreamPtr stream = ResourceGroupManager::getSingleton().openResource(fileName , groupName);666

667
// 读取文件头, 8个字节的结构668
WCollisionHeader header;669
stream->read(&header , sizeof(header));670

671
Vector3 vec3 = Vector3::ZERO;672
int col = 0;673
int row = 0;674
int preCol = 0; // 前一个数据块的列675
int preRow = 0; // 前一个数据块的行676
int number = 0;677
int k = 0;678
bool firstTime = true; // 第一次679

680
while (!stream->eof())681

{682
// 行列坐标, 决定WCollision的分块信息的683
// 如果把WCOliision做成一个mesh,每次都会全部查询,效率很低684
stream->read(&col, sizeof(row));685
stream->read(&row, sizeof(col));686

687
stream->read(&number, sizeof(number)); // 数据块的三角形数量688

689
// 读取此数据块的三角形顶点数据690
for (int i = 0; i < number * 3; ++ i)691

{692
stream->read(&vec3, sizeof(vec3)); 693
mWCollisionData.push_back(vec3);694
}695

696
if (mWCollisionData.size() == 0)697

{698
break;699
}700

701
// 初始化702
if (firstTime)703

{704
preCol = col;705
preRow = row;706
firstTime = false;707
} 708

709
// 行列坐标相连,就做成一个mesh710
if (col == preCol && (row - preRow) <= 1)711

{712
preCol = col;713
preRow = row;714
}715
else716

{717
// 生成718
ManualObject mo("mo");719
mo.begin("", RenderOperation::OT_TRIANGLE_LIST);720
for(size_t i = 0; i < mWCollisionData.size(); i += 3)721

{722
// 点1723
mo.position(mWCollisionData[i].x*mScaleX, mWCollisionData[i].y*mScaleY, mWCollisionData[i].z*mScaleZ);724
mo.colour(ColourValue(0, 0, 1));725

726
// 点2727
mo.position(mWCollisionData[i+1].x*mScaleX, mWCollisionData[i+1].y*mScaleY, mWCollisionData[i+1].z*mScaleZ);728
mo.colour(ColourValue(0, 0, 1));729

730
// 点3731
mo.position(mWCollisionData[i+2].x*mScaleX, mWCollisionData[i+2].y*mScaleY, mWCollisionData[i+2].z*mScaleZ);732
mo.colour(ColourValue(0, 0, 1));733

734
// 三角形索引顺序735
mo.triangle(i, i+1, i+2);736
}737
mo.end();738

739
String meshName = "WCollisionMesh"+StringConverter::toString(k);740
mo.convertToMesh(meshName, "TLBB");741
mManualMeshData.push_back(meshName);742

743
Entity* ent = mSceneMgr->createEntity("WCollison"+StringConverter::toString(k), meshName);744
mWCollisionEntData.push_back(ent); //745
ent->setCastShadows(false);746
ent->setQueryFlags(TERRAIN_QUERY_MASK);747

748
SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode(mCentre);749
node->attachObject(ent);750

751
mWCollisionData.clear(); // 752
firstTime = true;753
++ k;754
}755
} // end of while756
}757

758
//--------------------------------------------------------------------------------------------------------759
void TLBBTerrain::createTerrain()760


{761
// 生成材质762
LogManager::getSingleton().logMessage(LML_CRITICAL, "开始生成材质
");763
createManualMat();764

765
// 生成WCollision766
LogManager::getSingleton().logMessage(LML_CRITICAL, "开始生成WCollsion
");767
vector<String> vec;768
vec = StringUtil::split(mFileName, ".", 1);769
String tempStr = vec[0] + ".WCollision";770
createWCollision(tempStr, "TLBB");771

772
// 地形mesh773
LogManager::getSingleton().logMessage(LML_CRITICAL, "开始生成地形mesh
");774

775
// 判断地形大小是否能被tile整除,不能整除就需要矫正每行每列最后一个tile的大小776
// 在循环外部判断,就不用每次循环都判断,效率更高777
if (mXSize % mTileSize != 0 || mZSize % mTileSize != 0)778

{779
for (size_t matIndex = 0; matIndex < mMaterialNum; ++ matIndex)780

{781
// 材质名字782
// toString和StrStreamType是用std::ostringstream来做的,非常消耗cpu,尽量减少循环数次783
// 或者用sprintf来做784
String matName = "material" + StringConverter::toString(matIndex);785

786
// 同材质的mesh按tile区域生成787
for (size_t i = 0; i < mZSize; i += mTileSize)788

{789
for (size_t j = 0; j < mXSize; j += mTileSize)790

{791
// 矫正tile大小792
int tielSizeZ = mTileSize;793
int tileSizeX = mTileSize;794
if (mZSize - i < mTileSize)795

{796
tielSizeZ = mZSize - i;797
}798
if (mXSize - j < mTileSize)799

{800
tileSizeX = mXSize - j;801
}802
803
// 第一种方法 804
// 现有的地形检测暂时不支持ManualObject,以后考虑添加805
//createTileManualObject(j, i, tileSizeX, tielSizeZ, matName);806
807
// 第二种方法808
if (createTileMesh(j, i, tileSizeX, tielSizeZ, matName))809

{810
StringUtil::StrStreamType entName;811
StringUtil::StrStreamType meshName;812
entName << "tile[" << i << "]" << "[" << j << "]" << matName;813
meshName << "gridMesh[" << i << "]" << "[" << j << "]" << matName;814
Entity* entity = mSceneMgr->createEntity(entName.str(), meshName.str());815
entity->setCastShadows(false);816
entity->setQueryFlags(TERRAIN_QUERY_MASK);817
mSceneMgr->getRootSceneNode()->createChildSceneNode(mCentre)->attachObject(entity);818
}819
}820
}821
}822
}823
else824

{825
for (size_t matIndex = 0; matIndex < mMaterialNum; ++ matIndex)826

{827
// 材质名字828
// toString和StrStreamType是用std::ostringstream来做的,非常消耗cpu,尽量减少循环数次829
// 或者用sprintf来做830
String matName = "material" + StringConverter::toString(matIndex);831

832
// 同材质的mesh按tile区域生成833
for (size_t i = 0; i < mZSize; i += mTileSize)834

{835
for (size_t j = 0; j < mXSize; j += mTileSize)836

{837
838
// 第一种方法 839
// 现有的地形检测暂时不支持ManualObject,以后考虑添加840
//createTileManualObject(j, i, mTileSize, mTileSize, matName);841

842
// 第二种方法843
if (createTileMesh(j, i, mTileSize, mTileSize, matName))844

{845
StringUtil::StrStreamType entName;846
StringUtil::StrStreamType meshName;847
entName << "tile[" << i << "]" << "[" << j << "]" << matName;848
meshName << "gridMesh[" << i << "]" << "[" << j << "]" << matName;849
Entity* entity = mSceneMgr->createEntity(entName.str(), meshName.str());850
entity->setCastShadows(false);851
entity->setQueryFlags(TERRAIN_QUERY_MASK);852
mSceneMgr->getRootSceneNode()->createChildSceneNode(mCentre)->attachObject(entity);853
}854
}855
}856
}857
}858
}
213

被折叠的 条评论
为什么被折叠?



