/* * 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 m_relief; //! Resources data std::vector m_resources; //! Texture indices std::vector m_textures; //! Object ranks for mosaic objects std::vector 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 m_materials; //! Material for terrain points std::vector 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 m_buildingLevels; //! Wind speed Math::Vector m_wind; //! Global flying height limit float m_flyingMaxHeight; //! List of local flight limits std::vector m_flyingLimits; }; } // namespace Gfx