您的位置:首页 > 产品设计 > UI/UE

天龙八部生成地形mesh的源码

2011-09-17 14:27 288 查看
有个网友说他把我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


源文件部分重要代码:

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

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