1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
|
// * This file is part of the COLOBOT source code
// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see http://www.gnu.org/licenses/.
/**
* \file graphics/engine/terrain.h
* \brief Terrain rendering - CTerrain class
*/
#pragma once
#include "graphics/engine/engine.h"
class CInstanceManager;
// Graphics module namespace
namespace Gfx {
class CEngine;
class CWater;
//! Limit of slope considered a flat piece of land
const float TERRAIN_FLATLIMIT = (5.0f*Math::PI/180.0f);
/**
* \enum TerrainRes
* \brief Underground resource type
*/
enum TerrainRes
{
//! No resource
TR_NULL = 0,
//! Titanium
TR_STONE = 1,
//! Uranium
TR_URANIUM = 2,
//! Energy
TR_POWER = 3,
//! Vault keys
//@{
TR_KEY_A = 4,
TR_KEY_B = 5,
TR_KEY_C = 6,
TR_KEY_D = 7
//@}
};
/**
* \struct BuildingLevel
* \brief Flat level for building
*/
struct BuildingLevel
{
Math::Vector center;
float factor;
float min;
float max;
float level;
float height;
float bboxMinX;
float bboxMaxX;
float bboxMinZ;
float bboxMaxZ;
BuildingLevel()
{
factor = min = max = level = height = 0.0f;
bboxMinX = bboxMaxX = bboxMinZ = bboxMaxZ = 0.0f;
}
};
/**
* \struct TerrainMaterial
* \brief Material for ground surface
*/
struct TerrainMaterial
{
//! Unique ID
short id;
//! Texture
std::string texName;
//! UV texture coordinates
Math::Point uv;
//! Terrain hardness (defines e.g. sound of walking)
float hardness;
//! IDs of neighbor materials: up, right, down, left
char mat[4];
TerrainMaterial()
{
id = 0;
hardness = 0.0f;
mat[0] = mat[1] = mat[2] = mat[3] = 0;
}
};
/**
* \struct TerrainMaterialPoint
* \brief Material used for terrain point
*/
struct TerrainMaterialPoint
{
//! ID of material
short id;
//! IDs of neighbor materials: up, right, down, left
char mat[4];
TerrainMaterialPoint()
{
id = 0;
mat[0] = mat[1] = mat[2] = mat[3] = 0;
}
};
/**
* \struct FlyingLimit
* \brief Spherical limit of flight
*/
struct FlyingLimit
{
Math::Vector center;
float extRadius;
float intRadius;
float maxHeight;
FlyingLimit()
{
extRadius = intRadius = maxHeight = 0.0f;
}
};
/**
* \class CTerrain
* \brief Terrain loader/generator and manager
*
* \section Mapping Terrain mapping
*
* Terrain is created from relief textures specifying a XY plane with height
* values which are then scaled and translated into XZ surface forming the
* terrain of game level.
*
* The basic unit of terrain is called "brick", which is two triangles
* forming a quad. Bricks have constant size (brick size)
* in X and Z direction.
* Points forming the bricks correspond one-to-one to relief data points
* (pixels in relief image).
*
* Bricks are grouped into "mosaics". Mosaic is a square containing
* brickCount x brickCount bricks where brickCount is an even power of 2.
* Each mosaic corresponds to one created engine object.
*
* The whole terrain is also a square formed by mosaicCount * mosaicCount
* of mosaics.
*
* Image coordinates are converted in the following way to world coordinates
* of brick points (Wx, Wy, Wz - world coordinates, Ix, Iy - image coordinates,
* Pxy - pixel value at Ix,Iy):
*
* Wx = (Ix - brickCount*mosaicCount / 2.0f) * brickSize \n
* Wz = (Iy - brickCount*mosaicCount / 2.0f) * brickSize \n
* Wy = (Pxy / 255.0f) * reliefScale
*
* To create and initialize a terrain, you must call Generate() as the first function,
* setting the number of bricks, mosaics etc.
*
* \section Materials Materials and textures
*
* The terrain can be textured in two ways:
* - by applying texture index table
* - by specifying one or more "materials" that cover "material points"
*
* Textures are applied to subdivisions of mosaics (groups of bricks of size
* brickCount / textureSubdivCount).
*
* \subsection TextureIndexes Texture indexes
*
* Texture indexes specify the texture for each textured point by concatenating
* base name of texture, the index number and texture extension.
*
* Texture indexes are specified directly in InitTextures().
*
* \subsection TerrainMaterials Terrain materials
*
* Terrain materials are more sophisticated system. Each material is a texture,
* applied to one area, but specifying also the textures to use on surrounding areas:
* left, right, bottom and top.
*
* You specify one or more terrain materials in AddMaterial() function.
* The function will add a material for given circle on the ground, with some
* randomized matching of supplied materials and sophisticated logic for ensuring
* that borders between neighboring materials follow the specified rules.
*
* \subsection BuildingLevels Other features
*
* Terrain can have specified building levels - flat space expanses,
* where relief data is specifically adjusted to level space to allow
* construction of buildings.
*
* Undergound resources can be supplied by loading them from image like relief data.
*
* Terrain also specifies flying limits for player: one global level and possible
* additional spherical restrictions.
*/
class CTerrain
{
public:
CTerrain(CInstanceManager* iMan);
~CTerrain();
//! Generates a new flat terrain
bool Generate(int mosaicCount, int brickCountPow2, float brickSize, float vision, int depth, float hardness);
//! Initializes the names of textures to use for the land
bool InitTextures(const std::string& baseName, int* table, int dx, int dy);
//! Clears all terrain materials
void FlushMaterials();
//! Adds a terrain material the names of textures to use for the land
void AddMaterial(int id, const std::string& baseName, const Math::Point& uv,
int up, int right, int down, int left, float hardness);
//! Initializes all the ground with one material
bool InitMaterials(int id);
//! Generates a level in the terrain
bool GenerateMaterials(int *id, float min, float max, float slope, float freq, Math::Vector center, float radius);
//! Clears the relief data to zero
void FlushRelief();
//! Load relief from image
bool LoadRelief(const std::string& fileName, float scaleRelief, bool adjustBorder);
//! Load resources from image
bool LoadResources(const std::string& fileName);
//! Creates all objects of the terrain within the 3D engine
bool CreateObjects();
//! Modifies the terrain's relief
bool Terraform(const Math::Vector& p1, const Math::Vector& p2, float height);
//@{
//! Management of the wind
void SetWind(Math::Vector speed);
Math::Vector GetWind();
//@}
//! Gives the exact slope of the terrain at 2D (XZ) position
float GetFineSlope(const Math::Vector& pos);
//! Gives the approximate slope of the terrain at 2D (XZ) position
float GetCoarseSlope(const Math::Vector& pos);
//! Gives the normal vector at 2D (XZ) position
bool GetNormal(Math::Vector& n, const Math::Vector &p);
//! Returns the height of the ground level at 2D (XZ) position
float GetFloorLevel(const Math::Vector& pos, bool brut=false, bool water=false);
//! Returns the distance to the ground level from 3D position
float GetHeightToFloor(const Math::Vector& pos, bool brut=false, bool water=false);
//! Modifies the Y coordinate of 3D position to rest on the ground floor
bool AdjustToFloor(Math::Vector& pos, bool brut=false, bool water=false);
//! Adjusts 3D position so that it is within standard terrain boundaries
bool AdjustToStandardBounds(Math::Vector &pos);
//! Adjusts 3D position so that it is within terrain boundaries and the given margin
bool AdjustToBounds(Math::Vector& pos, float margin);
//! Returns the resource type available underground at 2D (XZ) position
TerrainRes GetResource(const Math::Vector& pos);
//! Empty the table of elevations
void FlushBuildingLevel();
//! Adds a new elevation for a building
bool AddBuildingLevel(Math::Vector center, float min, float max, float height, float factor);
//! Updates the elevation for a building when it was moved up (after a terraforming)
bool UpdateBuildingLevel(Math::Vector center);
//! Removes the elevation for a building when it was destroyed
bool DeleteBuildingLevel(Math::Vector center);
//! Returns the influence factor whether a position is on a possible rise
float GetBuildingFactor(const Math::Vector& pos);
//! Returns the hardness of the ground in a given place
float GetHardness(const Math::Vector& pos);
//! Returns number of mosaics
int GetMosaicCount();
//! Returns number of bricks in mosaic
int GetBrickCount();
//! Returns brick size
float GetBrickSize();
//! Returns the vertical scale of relief
float GetReliefScale();
//! Shows the flat areas on the ground
void ShowFlatGround(Math::Vector pos);
//! Calculates the radius of the largest flat area available
float GetFlatZoneRadius(Math::Vector center, float max);
//@{
//! Management of the global max flying height
void SetFlyingMaxHeight(float height);
float GetFlyingMaxHeight();
//@}
//! Empty the table of flying limits
void FlushFlyingLimit();
//! Adds a new flying limit
void AddFlyingLimit(Math::Vector center, float extRadius, float intRadius, float maxHeight);
//! Returns the maximum height of flight
float GetFlyingLimit(Math::Vector pos, bool noLimit);
protected:
//! Adds a point of elevation in the buffer of relief
bool AddReliefPoint(Math::Vector pos, float scaleRelief);
//! Adjust the edges of each mosaic to be compatible with all lower resolutions
void AdjustRelief();
//! Calculates a vector of the terrain
Math::Vector GetVector(int x, int y);
//! Calculates a vertex of the terrain
VertexTex2 GetVertex(int x, int y, int step);
//! Creates all objects of a mosaic
bool CreateMosaic(int ox, int oy, int step, int objRank, const Material& mat, float min, float max);
//! Creates all objects in a mesh square ground
bool CreateSquare(int x, int y);
//! Seeks a material based on its ID
TerrainMaterial* FindMaterial(int id);
//! Seeks a material based on neighbor values
int FindMaterialByNeighbors(char *mat);
//! Returns the texture name and UV coords to use for a given square
void GetTexture(int x, int y, std::string& name, Math::Point& uv);
//! Returns the height of the terrain
float GetHeight(int x, int y);
//! Decide whether a point is using the materials
bool CheckMaterialPoint(int x, int y, float min, float max, float slope);
//! Modifies the state of a point and its four neighbors, without testing if possible
void SetMaterialPoint(int x, int y, int id, char *mat);
//! Modifies the state of a point
bool ChangeMaterialPoint(int x, int y, int id);
//! Tests if a material can give a place, according to its four neighbors. If yes, puts the point.
bool CondChangeMaterialPoint(int x, int y, int id, char *mat);
//! Initializes material points array
void InitMaterialPoints();
//! Clears the material points
void FlushMaterialPoints();
//! Adjusts a position according to a possible rise
void AdjustBuildingLevel(Math::Vector &p);
protected:
CInstanceManager* m_iMan;
CEngine* m_engine;
CWater* m_water;
//! Relief data points
std::vector<float> m_relief;
//! Resources data
std::vector<unsigned char> m_resources;
//! Texture indices
std::vector<int> m_textures;
//! Object ranks for mosaic objects
std::vector<int> m_objRanks;
//! Number of mosaics (along one dimension)
int m_mosaicCount;
//! Number of bricks per mosaic (along one dimension)
int m_brickCount;
//! Number of terrain material dots (along one dimension)
int m_materialPointCount;
//! Size of single brick (along X and Z axis)
float m_brickSize;
//! Vertical (relief) scale
float m_scaleRelief;
//! Subdivision of material points in mosaic
int m_textureSubdivCount;
//! Number of different resolutions (1,2,3,4)
int m_depth;
//! Scale of texture mapping
float m_textureScale;
//! Vision before a change of resolution
float m_vision;
//! Base name for single texture
std::string m_texBaseName;
//! Extension for single texture
std::string m_texBaseExt;
//! Default hardness for level material
float m_defaultHardness;
//! True if using terrain material mapping
bool m_useMaterials;
//! Terrain materials
std::vector<TerrainMaterial> m_materials;
//! Material for terrain points
std::vector<TerrainMaterialPoint> m_materialPoints;
//! Maximum level ID (no ID is >= to this)
int m_maxMaterialID;
//! Internal counter for auto generation of material IDs
int m_materialAutoID;
std::vector<BuildingLevel> m_buildingLevels;
//! Wind speed
Math::Vector m_wind;
//! Global flying height limit
float m_flyingMaxHeight;
//! List of local flight limits
std::vector<FlyingLimit> m_flyingLimits;
};
} // namespace Gfx
|