summaryrefslogtreecommitdiffstats
path: root/src/graphics/engine/terrain.h
blob: a2bb36aead18859c342e2f81f4adf17ad849f7e6 (plain)
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
425
/*
 * This file is part of the Colobot: Gold Edition source code
 * Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
 * http://epsiteс.ch; http://colobot.info; http://github.com/colobot
 *
 * 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://gnu.org/licenses
 */

/**
 * \file graphics/engine/terrain.h
 * \brief Terrain rendering - CTerrain class
 */

#pragma once


#include "graphics/engine/engine.h"


// 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.
 *
 * Underground 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();
    ~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, resources and all other associated data
    void        FlushRelief();
    //! Load relief from image
    bool        LoadRelief(const std::string& fileName, float scaleRelief, bool adjustBorder);
    //! Load ramdomized relief
    bool        RandomizeRelief();

    //! 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);
    //! 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:
    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