From e738c55b73a8d635cac34fb3c37f3758ca4f1671 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Tue, 26 Jun 2012 23:39:31 +0200 Subject: Removed old code and build target - removed directory with old target - changed CMakeLists.txt to new target only and temporarily commented out reference to CBot - updated README --- src/old/terrain.cpp | 2270 --------------------------------------------------- 1 file changed, 2270 deletions(-) delete mode 100644 src/old/terrain.cpp (limited to 'src/old/terrain.cpp') diff --git a/src/old/terrain.cpp b/src/old/terrain.cpp deleted file mode 100644 index 9804261..0000000 --- a/src/old/terrain.cpp +++ /dev/null @@ -1,2270 +0,0 @@ -// * This file is part of the COLOBOT source code -// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch -// * -// * 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/. - -// terrain.cpp - - -#include -#include -#include - -#include "common/struct.h" -#include "math/const.h" -#include "math/geometry.h" -#include "old/d3dengine.h" -#include "old/d3dmath.h" -#include "old/d3dutil.h" -#include "common/language.h" -#include "common/event.h" -#include "common/misc.h" -#include "common/iman.h" -#include "old/math3d.h" -#include "old/modfile.h" -#include "old/water.h" -#include "old/terrain.h" - - -const int BMPHEAD = 1078; - - - -// Constructor of the terrain. - -CTerrain::CTerrain(CInstanceManager* iMan) -{ - m_iMan = iMan; - m_iMan->AddInstance(CLASS_TERRAIN, this); - - m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); - m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER); - - m_mosaic = 20; - m_brick = 1<<4; - m_size = 10.0f; - m_vision = 200.0f; - m_relief = 0; - m_texture = 0; - m_objRank = 0; - m_scaleMapping = 0.01f; - m_scaleRelief = 1.0f; - m_subdivMapping = 1; - m_depth = 2; - m_texBaseName[0]= 0; - m_texBaseExt[0] = 0; - m_bMultiText = true; - m_bLevelText = false; - m_resources = 0; - m_levelMatTotal = 0; - m_levelMatMax = 0; - m_levelDot = 0; - m_wind = Math::Vector(0.0f, 0.0f, 0.0f); - m_defHardness = 0.5f; - - FlushBuildingLevel(); - FlushFlyingLimit(); -} - -// Destructor of the terrain. - -CTerrain::~CTerrain() -{ - free(m_relief); - free(m_texture); - free(m_objRank); - free(m_resources); -} - - -// Generates a new flat terrain. -// The terrain is composed of mosaics, themselves composed of bricks. -// Each brick is composed of two triangles. -// mosaic: number of mosaics along the axes X and Z -// brick: number of bricks (power of 2) -// size: size of a brick along the axes X and Z -// vision: vision before a change of resolution -// scaleMapping: scale textures for mapping -// -// ^ z -// | <---> brick*size -// +---+---+---+---+ -// | | | |_|_| mosaic = 4 -// | | | | | | brick = 2 (brickP2=1) -// +---+---+---+---+ -// |\ \| | | | -// |\ \| | | | -// +---+---o---+---+---> x -// | | | | | -// | | | | | -// +---+---+---+---+ -// | | | | | The land is viewed from above here. -// | | | | | -// +---+---+---+---+ -// <---------------> mosaic*brick*size - -bool CTerrain::Generate(int mosaic, int brickP2, float size, float vision, - int depth, float hardness) -{ - int dim; - - m_mosaic = mosaic; - m_brick = 1<SetTerrainVision(vision); - - m_bMultiText = true; - m_bLevelText = false; - m_scaleMapping = 1.0f/(m_brick*m_size); - m_subdivMapping = 1; - - dim = (m_mosaic*m_brick+1)*(m_mosaic*m_brick+1); - m_relief = (float*)malloc(sizeof(float)*dim); - ZeroMemory(m_relief, sizeof(float)*dim); - - dim = m_mosaic*m_subdivMapping*m_mosaic*m_subdivMapping; - m_texture = (int*)malloc(sizeof(int)*dim); - ZeroMemory(m_texture, sizeof(int)*dim); - - dim = m_mosaic*m_mosaic; - m_objRank = (int*)malloc(sizeof(int)*dim); - ZeroMemory(m_objRank, sizeof(int)*dim); - - return true; -} - - -int CTerrain::RetMosaic() -{ - return m_mosaic; -} - -int CTerrain::RetBrick() -{ - return m_brick; -} - -float CTerrain::RetSize() -{ - return m_size; -} - -float CTerrain::RetScaleRelief() -{ - return m_scaleRelief; -} - - -// Initializes the names of textures to use for the land. - -bool CTerrain::InitTextures(char* baseName, int* table, int dx, int dy) -{ - int x, y; - char* p; - - m_bLevelText = false; - - strcpy(m_texBaseName, baseName); - p = strchr(m_texBaseName, '.'); // p <- ^beginning of the extension - if ( p == 0 ) - { - strcpy(m_texBaseExt, ".tga"); - } - else - { - strcpy(m_texBaseExt, p); // m_texBaseExt <- ".tga" or ".bmp" - *p = 0; // m_texBaseName <- name without extension - } - - for ( y=0 ; y= MAXMATTERRAIN-1 ) return false; - - LevelOpenTable(); - - if ( id == 0 ) - { - id = m_levelID++; // puts an ID internal standard - } - - strcpy(m_levelMat[i].texName, baseName); - m_levelMat[i].id = id; - m_levelMat[i].u = u; - m_levelMat[i].v = v; - m_levelMat[i].mat[0] = up; - m_levelMat[i].mat[1] = right; - m_levelMat[i].mat[2] = down; - m_levelMat[i].mat[3] = left; - m_levelMat[i].hardness = hardness; - - if ( m_levelMatMax < up+1 ) m_levelMatMax = up+1; - if ( m_levelMatMax < right+1 ) m_levelMatMax = right+1; - if ( m_levelMatMax < down+1 ) m_levelMatMax = down+1; - if ( m_levelMatMax < left+1 ) m_levelMatMax = left+1; - - m_bLevelText = true; - m_subdivMapping = 4; - - m_levelMatTotal ++; - return true; -} - - -// Load relief from a BMP file. -// The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1. -// The image must be 8 bits/pixel, 256 colors with a standard pallet. - -// Converts coordinated image (x;y) -> world (x;-;z) : -// Wx = 5*Ix-400 -// Wz = -(5*Iy-400) - -// Converts coordinated world (x;-;z) -> image (x;y) : -// Ix = (400+Wx)/5 -// Iy = (400-Wz)/5 - -bool CTerrain::ResFromBMP(const char* filename) -{ - FILE* file; - int size, sizem; - - file = fopen(filename, "rb"); - if ( file == NULL ) return false; - - size = (m_mosaic*m_brick)+1; - sizem = ((size+4-1)/4)*4; // upper size multiple of 4 - - if ( m_resources != 0 ) - { - free(m_resources); - } - - m_resources = (unsigned char*)malloc(BMPHEAD+sizem*size); - fread(m_resources, BMPHEAD+sizem*size, 1, file); - - if ( m_resources[18] != (size&0xff) || m_resources[19] != (size>>8) || - m_resources[22] != (size&0xff) || m_resources[23] != (size>>8) ) - { - free(m_resources); - m_resources = 0; - fclose(file); - return false; - } - - fclose(file); - return true; -} - -// Returns the resource type available underground. - -TerrainRes CTerrain::RetResource(const Math::Vector &p) -{ - int x, y, size, sizem, ress; - - if ( m_resources == 0 ) return TR_NULL; - - x = (int)((p.x + (m_mosaic*m_brick*m_size)/2.0f)/m_size); - y = (int)((p.z + (m_mosaic*m_brick*m_size)/2.0f)/m_size); - - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return TR_NULL; - - size = (m_mosaic*m_brick)+1; - sizem = ((size+4-1)/4)*4; // upper size multiple of 4 - - ress = m_resources[BMPHEAD+x+sizem*y]; - if ( ress == 5 ) return TR_STONE; // red? - if ( ress == 35 ) return TR_URANIUM; // yellow? - if ( ress == 30 ) return TR_POWER; // green? - if ( ress == 24 ) return TR_KEYa; // ~green? - if ( ress == 25 ) return TR_KEYb; // ~green? - if ( ress == 26 ) return TR_KEYc; // ~green? - if ( ress == 27 ) return TR_KEYd; // ~green? - - return TR_NULL; -} - - -// Initializes a completely flat terrain. - -void CTerrain::FlushRelief() -{ - free(m_relief); - m_relief = 0; -} - -// Load relief from a BMP file. -// The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1. -// The image must be 8 bits/pixel, 256 gray scale: -// white = ground (y=0) -// black = mountain (y=255*scaleRelief) - -// Converts coordinated image(x;y) -> world (x;-;z) : -// Wx = 5*Ix-400 -// Wz = -(5*Iy-400) - -// Converts coordinated world (x;-;z) -> image (x;y) : -// Ix = (400+Wx)/5 -// Iy = (400-Wz)/5 - -bool CTerrain::ReliefFromBMP(const char* filename, float scaleRelief, - bool adjustBorder) -{ - FILE* file; - unsigned char* buffer; - int size, sizem, x, y; - float level, limit, dist, border; - - m_scaleRelief = scaleRelief; - - file = fopen(filename, "rb"); - if ( file == NULL ) return false; - - size = (m_mosaic*m_brick)+1; - sizem = ((size+4-1)/4)*4; // upper size multiple of 4 - - buffer = (unsigned char*)malloc(BMPHEAD+sizem*size); - fread(buffer, BMPHEAD+sizem*size, 1, file); - - if ( buffer[18] != (size&0xff) || buffer[19] != (size>>8) || - buffer[22] != (size&0xff) || buffer[23] != (size>>8) ) - { - free(buffer); - fclose(file); - return false; - } - - limit = 0.9f; - for ( y=0 ; y limit && adjustBorder ) - { - dist = (dist-limit)/(1.0f-limit); // 0..1 - if ( dist > 1.0f ) dist = 1.0f; - border = 300.0f+Math::Rand()*20.0f; - level = level+dist*(border-level); - } - - m_relief[x+y*size] = level; - } - } - - free(buffer); - fclose(file); - return true; -} - -// Adds a point of elevation in the buffer of relief. - -bool CTerrain::ReliefAddDot(Math::Vector pos, float scaleRelief) -{ - float dim; - int size, x, y; - - dim = (m_mosaic*m_brick*m_size)/2.0f; - size = (m_mosaic*m_brick)+1; - - pos.x = (pos.x+dim)/m_size; - pos.z = (pos.z+dim)/m_size; - - x = (int)pos.x; - y = (int)pos.z; - - if ( x < 0 || x >= size || - y < 0 || y >= size ) return false; - - if ( m_relief[x+y*size] < pos.y*scaleRelief ) - { - m_relief[x+y*size] = pos.y*scaleRelief; - } - return true; -} - -// Load relief from a DXF file. - -bool CTerrain::ReliefFromDXF(const char* filename, float scaleRelief) -{ - FILE* file = NULL; - char line[100]; - int command, rankSommet, nbSommet, nbFace, size; - Math::Vector* table; - bool bWaitNbSommet; - bool bWaitNbFace; - bool bWaitSommetX; - bool bWaitSommetY; - bool bWaitSommetZ; - bool bWaitFaceX; - bool bWaitFaceY; - bool bWaitFaceZ; - float x,y,z; - int p1,p2,p3; - - ZeroMemory(m_relief, sizeof(float)*(m_mosaic*m_brick+1)*(m_mosaic*m_brick+1)); - - file = fopen(filename, "r"); - if ( file == NULL ) return false; - - size = (m_mosaic*m_brick)+1; - table = (Math::Vector*)malloc(sizeof(Math::Vector)*size*size); - - rankSommet = 0; - bWaitNbSommet = false; - bWaitNbFace = false; - bWaitSommetX = false; - bWaitSommetY = false; - bWaitSommetZ = false; - bWaitFaceX = false; - bWaitFaceY = false; - bWaitFaceZ = false; - - while ( fgets(line, 100, file) != NULL ) - { - sscanf(line, "%d", &command); - if ( fgets(line, 100, file) == NULL ) break; - - if ( command == 66 ) - { - bWaitNbSommet = true; - } - - if ( command == 71 && bWaitNbSommet ) - { - bWaitNbSommet = false; - sscanf(line, "%d", &nbSommet); - if ( nbSommet > size*size ) nbSommet = size*size; - rankSommet = 0; - bWaitNbFace = true; - } - - if ( command == 72 && bWaitNbFace ) - { - bWaitNbFace = false; - sscanf(line, "%d", &nbFace); - bWaitSommetX = true; - } - - if ( command == 10 && bWaitSommetX ) - { - bWaitSommetX = false; - sscanf(line, "%f", &x); - bWaitSommetY = true; - } - - if ( command == 20 && bWaitSommetY ) - { - bWaitSommetY = false; - sscanf(line, "%f", &y); - bWaitSommetZ = true; - } - - if ( command == 30 && bWaitSommetZ ) - { - bWaitSommetZ = false; - sscanf(line, "%f", &z); - - nbSommet --; - if ( nbSommet >= 0 ) - { - Math::Vector p(x,z,y); // permutation of Y and Z! - table[rankSommet++] = p; - bWaitSommetX = true; - } - else - { - bWaitFaceX = true; - } - } - - if ( command == 71 && bWaitFaceX ) - { - bWaitFaceX = false; - sscanf(line, "%d", &p1); - if ( p1 < 0 ) p1 = -p1; - bWaitFaceY = true; - } - - if ( command == 72 && bWaitFaceY ) - { - bWaitFaceY = false; - sscanf(line, "%d", &p2); - if ( p2 < 0 ) p2 = -p2; - bWaitFaceZ = true; - } - - if ( command == 73 && bWaitFaceZ ) - { - bWaitFaceZ = false; - sscanf(line, "%d", &p3); - if ( p3 < 0 ) p3 = -p3; - - nbFace --; - if ( nbFace >= 0 ) - { - ReliefAddDot(table[p3-1], scaleRelief); - ReliefAddDot(table[p2-1], scaleRelief); - ReliefAddDot(table[p1-1], scaleRelief); - bWaitFaceX = true; - } - } - - } - - free(table); - fclose(file); - return true; -} - - -// Adjusts a position so that it does not exceed the boundaries. - -void CTerrain::LimitPos(Math::Vector &pos) -{ - float dim; - -#if _TEEN - dim = (m_mosaic*m_brick*m_size)/2.0f*0.98f; -#else - dim = (m_mosaic*m_brick*m_size)/2.0f*0.92f; -#endif - - if ( pos.x < -dim ) pos.x = -dim; - if ( pos.x > dim ) pos.x = dim; - if ( pos.z < -dim ) pos.z = -dim; - if ( pos.z > dim ) pos.z = dim; -} - - -// Adjust the edges of each mosaic to be compatible with all lower resolutions. - -void CTerrain::AdjustRelief() -{ - int x, y, xx, yy, ii, b; - float level1, level2; - - if ( m_depth == 1 ) return; - - ii = m_mosaic*m_brick+1; - b = 1<<(m_depth-1); - - for ( y=0 ; y= 0 && x <= m_mosaic*m_brick && - y >= 0 && y <= m_mosaic*m_brick ) - { - p.y = m_relief[x+y*(m_mosaic*m_brick+1)]; - } - else - { - p.y = 0.0f; - } - - return p; -} - -// Calculates a vertex of the terrain. -// Calculates a normal soft, taking into account the six adjacent triangles: -// -// ^ y -// | -// b---c---+ -// |\ |\ | -// | \| \| -// a---o---d -// |\ |\ | -// | \| \| -// +---f---e--> x - -D3DVERTEX2 CTerrain::RetVertex(int x, int y, int step) -{ - D3DVERTEX2 v; - Math::Vector o, oo, a,b,c,d,e,f, n, s; - int brick; - - o = RetVector(x, y); - v.x = o.x; - v.y = o.y; - v.z = o.z; - - a = RetVector(x-step, y ); - b = RetVector(x-step, y+step); - c = RetVector(x, y+step); - d = RetVector(x+step, y ); - e = RetVector(x+step, y-step); - f = RetVector(x, y-step); - - s = Math::Vector(0.0f, 0.0f, 0.0f); - - if ( x-step >= 0 && y+step <= m_mosaic*m_brick+1 ) - { - s += Math::NormalToPlane(b,a,o); - s += Math::NormalToPlane(c,b,o); - } - - if ( x+step <= m_mosaic*m_brick+1 && y+step <= m_mosaic*m_brick+1 ) - { - s += Math::NormalToPlane(d,c,o); - } - - if ( x+step <= m_mosaic*m_brick+1 && y-step >= 0 ) - { - s += Math::NormalToPlane(e,d,o); - s += Math::NormalToPlane(f,e,o); - } - - if ( x-step >= 0 && y-step >= 0 ) - { - s += Math::NormalToPlane(a,f,o); - } - - s = Normalize(s); - v.nx = s.x; - v.ny = s.y; - v.nz = s.z; - - if ( m_bMultiText ) - { - brick = m_brick/m_subdivMapping; - oo = RetVector((x/brick)*brick, (y/brick)*brick); - o = RetVector(x, y); - v.tu = (o.x-oo.x)*m_scaleMapping*m_subdivMapping; - v.tv = 1.0f - (o.z-oo.z)*m_scaleMapping*m_subdivMapping; - } - else - { - v.tu = o.x*m_scaleMapping; - v.tv = o.z*m_scaleMapping; - } - - return v; -} - -// Creates all objects of a mosaic. -// The origin of mosaic is his center. -// -// ^ z -// | -// | 2---4---6-- -// | |\ |\ |\ -// | | \| \| -// | 1---3---5--- ... -// | -// +-------------------> x - -bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, - const D3DMATERIAL7 &mat, - float min, float max) -{ - Math::Matrix transform; - D3DVERTEX2 o, p1, p2; - D3DObjLevel6* buffer; - Math::Point uv; - int brick, total, size, mx, my, x, y, xx, yy, i; - char texName1[20]; - char texName2[20]; - float pixel, dp; - - if ( step == 1 && m_engine->RetGroundSpot() ) - { - i = (ox/5) + (oy/5)*(m_mosaic/5); - sprintf(texName2, "shadow%.2d.tga", i); - } - else - { - texName2[0] = 0; - } - - brick = m_brick/m_subdivMapping; - - o = RetVertex(ox*m_brick+m_brick/2, oy*m_brick+m_brick/2, step); - total = ((brick/step)+1)*2; - size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1); - - pixel = 1.0f/256.0f; // 1 pixel cover (*) -//? dp = 0.5f/512.0f; - dp = 1.0f/512.0f; - - for ( my=0 ; mytotalPossible = total; - buffer->totalUsed = total; - buffer->type = D3DTYPE6S; - buffer->material = mat; - if ( m_bMultiText ) - { -//? buffer->state = D3DSTATENORMAL; - buffer->state = D3DSTATEWRAP; - } - else - { - buffer->state = D3DSTATEWRAP; - } - buffer->state |= D3DSTATESECOND; - if ( step == 1 ) - { - buffer->state |= D3DSTATEDUALb; - } - i = 0; - for ( x=0 ; x<=brick ; x+=step ) - { - p1 = RetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+0 , step); - p2 = RetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+step, step); - p1.x -= o.x; p1.z -= o.z; - p2.x -= o.x; p2.z -= o.z; - - if ( m_bMultiText ) - { - if ( x == 0 ) - { - p1.tu = 0.0f+(0.5f/256.0f); - p2.tu = 0.0f+(0.5f/256.0f); - } - if ( x == brick ) - { - p1.tu = 1.0f-(0.5f/256.0f); - p2.tu = 1.0f-(0.5f/256.0f); - } - if ( y == 0 ) - { - p1.tv = 1.0f-(0.5f/256.0f); - } - if ( y == brick-step ) - { - p2.tv = 0.0f+(0.5f/256.0f); - } - } - - if ( m_bLevelText ) - { - p1.tu /= m_subdivMapping; // 0..1 -> 0..0.25 - p1.tv /= m_subdivMapping; - p2.tu /= m_subdivMapping; - p2.tv /= m_subdivMapping; - - if ( x == 0 ) - { - p1.tu = 0.0f+dp; - p2.tu = 0.0f+dp; - } - if ( x == brick ) - { - p1.tu = (1.0f/m_subdivMapping)-dp; - p2.tu = (1.0f/m_subdivMapping)-dp; - } - if ( y == 0 ) - { - p1.tv = (1.0f/m_subdivMapping)-dp; - } - if ( y == brick-step ) - { - p2.tv = 0.0f+dp; - } - - p1.tu += uv.x; - p1.tv += uv.y; - p2.tu += uv.x; - p2.tv += uv.y; - } - -#if 1 - xx = mx*(m_brick/m_subdivMapping) + x; - yy = my*(m_brick/m_subdivMapping) + y; - p1.tu2 = ((float)(ox%5)*m_brick+xx+0.0f)/(m_brick*5); - p1.tv2 = ((float)(oy%5)*m_brick+yy+0.0f)/(m_brick*5); - p2.tu2 = ((float)(ox%5)*m_brick+xx+0.0f)/(m_brick*5); - p2.tv2 = ((float)(oy%5)*m_brick+yy+1.0f)/(m_brick*5); - - // Correction for 1 pixel cover (*). - p1.tu2 = (p1.tu2+pixel)*(1.0f-pixel)/(1.0f+pixel); - p1.tv2 = (p1.tv2+pixel)*(1.0f-pixel)/(1.0f+pixel); - p2.tu2 = (p2.tu2+pixel)*(1.0f-pixel)/(1.0f+pixel); - p2.tv2 = (p2.tv2+pixel)*(1.0f-pixel)/(1.0f+pixel); -#endif - - buffer->vertex[i++] = p1; - buffer->vertex[i++] = p2; - } - m_engine->AddQuick(objRank, buffer, texName1, texName2, min, max, true); - } - } - } - - transform.LoadIdentity(); - transform.Set(1, 4, o.x); - transform.Set(3, 4, o.z); - m_engine->SetObjectTransform(objRank, transform); - - return true; -} - -// (*) There is 1 pixel cover around each of the 16 surfaces: -// -// |<--------------256-------------->| -// | |<----------254---------->| | -// |---|---|---|-- ... --|---|---|---| -// | 0.0 1.0 | -// | | | | -// 0.0 min max 1.0 -// -// The uv coordinates used for texturing are between min and max (instead of 0 and 1). -// This allows to exclude the pixels situated in a margin of a pixel around the surface. - - -// Seeks a materials based on theirs identifier. - -TerrainMaterial* CTerrain::LevelSearchMat(int id) -{ - int i; - - for ( i=0 ; itexName); - strcpy(name, tm->texName); - uv.x = tm->u; - uv.y = tm->v; - } -} - -// Returns the height of the terrain. - -float CTerrain::LevelRetHeight(int x, int y) -{ - int size; - - size = (m_mosaic*m_brick+1); - - if ( x < 0 ) x = 0; - if ( x >= size ) x = size-1; - if ( y < 0 ) y = 0; - if ( y >= size ) y = size-1; - - return m_relief[x+y*size]; -} - -// Decide whether a point is using the materials. - -bool CTerrain::LevelGetDot(int x, int y, float min, float max, float slope) -{ - float hc, h[4]; - int i; - - hc = LevelRetHeight(x, y); - h[0] = LevelRetHeight(x+0, y+1); - h[1] = LevelRetHeight(x+1, y+0); - h[2] = LevelRetHeight(x+0, y-1); - h[3] = LevelRetHeight(x-1, y+0); - - if ( hc < min || - hc > max ) return false; - - if ( slope == 0.0f ) - { - return true; - } - - if ( slope > 0.0f ) - { - for ( i=0 ; i<4 ; i++ ) - { - if ( fabs(hc-h[i]) >= slope ) - { - return false; - } - } - return true; - } - - if ( slope < 0.0f ) - { - for ( i=0 ; i<4 ; i++ ) - { - if ( fabs(hc-h[i]) < -slope ) - { - return false; - } - } - return true; - } - - return false; -} - -// Seeks if material exists. -// Returns the index within m_levelMat or -1 if there is not. -// m_levelMat[i].id gives the identifier. - -int CTerrain::LevelTestMat(char *mat) -{ - int i; - - for ( i=0 ; imat[0] != mat[0] || - tm->mat[1] != mat[1] || - tm->mat[2] != mat[2] || - tm->mat[3] != mat[3] ) // id incompatible with mat? - { - ii = LevelTestMat(mat); - if ( ii == -1 ) return; - id = m_levelMat[ii].id; // looking for a id compatible with mat - } - - // Changes the point. - m_levelDot[x+y*m_levelDotSize].id = id; - m_levelDot[x+y*m_levelDotSize].mat[0] = mat[0]; - m_levelDot[x+y*m_levelDotSize].mat[1] = mat[1]; - m_levelDot[x+y*m_levelDotSize].mat[2] = mat[2]; - m_levelDot[x+y*m_levelDotSize].mat[3] = mat[3]; - - // Changes the lower neighbor. - if ( (x+0) >= 0 && (x+0) < m_levelDotSize && - (y-1) >= 0 && (y-1) < m_levelDotSize ) - { - i = (x+0)+(y-1)*m_levelDotSize; - if ( m_levelDot[i].mat[0] != mat[2] ) - { - m_levelDot[i].mat[0] = mat[2]; - ii = LevelTestMat(m_levelDot[i].mat); - if ( ii != -1 ) - { - m_levelDot[i].id = m_levelMat[ii].id; - } - } - } - - // Modifies the left neighbor. - if ( (x-1) >= 0 && (x-1) < m_levelDotSize && - (y+0) >= 0 && (y+0) < m_levelDotSize ) - { - i = (x-1)+(y+0)*m_levelDotSize; - if ( m_levelDot[i].mat[1] != mat[3] ) - { - m_levelDot[i].mat[1] = mat[3]; - ii = LevelTestMat(m_levelDot[i].mat); - if ( ii != -1 ) - { - m_levelDot[i].id = m_levelMat[ii].id; - } - } - } - - // Changes the upper neighbor. - if ( (x+0) >= 0 && (x+0) < m_levelDotSize && - (y+1) >= 0 && (y+1) < m_levelDotSize ) - { - i = (x+0)+(y+1)*m_levelDotSize; - if ( m_levelDot[i].mat[2] != mat[0] ) - { - m_levelDot[i].mat[2] = mat[0]; - ii = LevelTestMat(m_levelDot[i].mat); - if ( ii != -1 ) - { - m_levelDot[i].id = m_levelMat[ii].id; - } - } - } - - // Changes the right neighbor. - if ( (x+1) >= 0 && (x+1) < m_levelDotSize && - (y+0) >= 0 && (y+0) < m_levelDotSize ) - { - i = (x+1)+(y+0)*m_levelDotSize; - if ( m_levelDot[i].mat[3] != mat[1] ) - { - m_levelDot[i].mat[3] = mat[1]; - ii = LevelTestMat(m_levelDot[i].mat); - if ( ii != -1 ) - { - m_levelDot[i].id = m_levelMat[ii].id; - } - } - } -} - -// Tests if a material can give a place, according to its four neighbors. -// If yes, puts the point. - -bool CTerrain::LevelIfDot(int x, int y, int id, char *mat) -{ - char test[4]; - - // Compatible with lower neighbor? - if ( x+0 >= 0 && x+0 < m_levelDotSize && - y-1 >= 0 && y-1 < m_levelDotSize ) - { - test[0] = mat[2]; - test[1] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[1]; - test[2] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[2]; - test[3] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[3]; - - if ( LevelTestMat(test) == -1 ) return false; - } - - // Compatible with left neighbor? - if ( x-1 >= 0 && x-1 < m_levelDotSize && - y+0 >= 0 && y+0 < m_levelDotSize ) - { - test[0] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[0]; - test[1] = mat[3]; - test[2] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[2]; - test[3] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[3]; - - if ( LevelTestMat(test) == -1 ) return false; - } - - // Compatible with upper neighbor? - if ( x+0 >= 0 && x+0 < m_levelDotSize && - y+1 >= 0 && y+1 < m_levelDotSize ) - { - test[0] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[0]; - test[1] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[1]; - test[2] = mat[0]; - test[3] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[3]; - - if ( LevelTestMat(test) == -1 ) return false; - } - - // Compatible with right neighbor? - if ( x+1 >= 0 && x+1 < m_levelDotSize && - y+0 >= 0 && y+0 < m_levelDotSize ) - { - test[0] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[0]; - test[1] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[1]; - test[2] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[2]; - test[3] = mat[1]; - - if ( LevelTestMat(test) == -1 ) return false; - } - - LevelSetDot(x, y, id, mat); // puts the point - return true; -} - -// Modifies the state of a point. - -bool CTerrain::LevelPutDot(int x, int y, int id) -{ - TerrainMaterial *tm; - char mat[4]; - int up, right, down, left; - - x /= m_brick/m_subdivMapping; - y /= m_brick/m_subdivMapping; - - if ( x < 0 || x >= m_levelDotSize || - y < 0 || y >= m_levelDotSize ) return false; - - tm = LevelSearchMat(id); - if ( tm == 0 ) return false; - - // Tries without changing neighbors. - if ( LevelIfDot(x, y, id, tm->mat) ) return true; - - // Tries changing a single neighbor (4x). - for ( up=0 ; upmat[1]; - mat[2] = tm->mat[2]; - mat[3] = tm->mat[3]; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - - for ( right=0 ; rightmat[0]; - mat[1] = right; - mat[2] = tm->mat[2]; - mat[3] = tm->mat[3]; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - - for ( down=0 ; downmat[0]; - mat[1] = tm->mat[1]; - mat[2] = down; - mat[3] = tm->mat[3]; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - - for ( left=0 ; leftmat[0]; - mat[1] = tm->mat[1]; - mat[2] = tm->mat[2]; - mat[3] = left; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - - // Tries changing two neighbors (6x). - for ( up=0 ; upmat[1]; - mat[2] = down; - mat[3] = tm->mat[3]; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - for ( right=0 ; rightmat[0]; - mat[1] = right; - mat[2] = tm->mat[2]; - mat[3] = left; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - for ( up=0 ; upmat[2]; - mat[3] = tm->mat[3]; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - for ( right=0 ; rightmat[0]; - mat[1] = right; - mat[2] = down; - mat[3] = tm->mat[3]; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - for ( down=0 ; downmat[0]; - mat[1] = tm->mat[1]; - mat[2] = down; - mat[3] = left; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - for ( up=0 ; upmat[1]; - mat[2] = tm->mat[2]; - mat[3] = left; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - // Tries changing all the neighbors. - for ( up=0 ; upmat[j]; - } - } - - return true; -} - -// Generates a level in the terrain. - -bool CTerrain::LevelGenerate(int *id, float min, float max, - float slope, float freq, - Math::Vector center, float radius) -{ - TerrainMaterial *tm; - Math::Vector pos; - int i, numID, x, y, xx, yy, group, rnd; - float dim; - - static char random[100] = - { - 84,25,12, 6,34,52,85,38,97,16, - 21,31,65,19,62,40,72,22,48,61, - 56,47, 8,53,73,77, 4,91,26,88, - 76, 1,44,93,39,11,71,17,98,95, - 88,83,18,30, 3,57,28,49,74, 9, - 32,13,96,66,15,70,36,10,59,94, - 45,86, 2,29,63,42,51, 0,79,27, - 54, 7,20,69,89,23,64,43,81,92, - 90,33,46,14,67,35,50, 5,87,60, - 68,55,24,78,41,75,58,80,37,82, - }; - - i = 0; - while ( id[i] != 0 ) - { - tm = LevelSearchMat(id[i++]); - if ( tm == 0 ) return false; - } - numID = i; - - group = m_brick/m_subdivMapping; - - if ( radius > 0.0f && radius < 5.0f ) // just a square? - { - dim = (m_mosaic*m_brick*m_size)/2.0f; - - xx = (int)((center.x+dim)/m_size); - yy = (int)((center.z+dim)/m_size); - - x = xx/group; - y = yy/group; - - tm = LevelSearchMat(id[0]); - if ( tm != 0 ) - { - LevelSetDot(x, y, id[0], tm->mat); // puts the point - } -//? LevelPutDot(xx,yy, id[0]); - } - else - { - for ( y=0 ; y radius ) continue; - } - - if ( freq < 100.0f ) - { - rnd = random[(x%10)+(y%10)*10]; - if ( (float)rnd > freq ) continue; - } - - xx = x*group + group/2; - yy = y*group + group/2; - - if ( LevelGetDot(xx,yy, min, max, slope) ) - { - rnd = random[(x%10)+(y%10)*10]; - i = rnd%numID; - LevelPutDot(xx,yy, id[i]); - } - } - } - } - - return true; -} - -// Initializes an table with empty levels. - -void CTerrain::LevelOpenTable() -{ - int i, j; - - if ( !m_bLevelText ) return; - if ( m_levelDot != 0 ) return; // already allocated - - m_levelDotSize = (m_mosaic*m_brick)/(m_brick/m_subdivMapping)+1; - m_levelDot = (DotLevel*)malloc(m_levelDotSize*m_levelDotSize*sizeof(DotLevel)); - - for ( i=0 ; iCreateObject(); - m_engine->SetObjectType(objRank, TYPETERRAIN); // it is a terrain - - m_objRank[x+y*m_mosaic] = objRank; - - if ( bMultiRes ) - { - min = 0.0f; - max = m_vision; - max *= m_engine->RetClippingDistance(); - for ( step=0 ; step tp2.x ) - { - x = tp1.x; - tp1.x = tp2.x; - tp2.x = x; - } - - if ( tp1.y > tp2.y ) - { - y = tp1.y; - tp1.y = tp2.y; - tp2.y = y; - } - - size = (m_mosaic*m_brick)+1; - - // Calculates the current average height. - avg = 0.0f; - nb = 0; - for ( y=tp1.y ; y<=tp2.y ; y++ ) - { - for ( x=tp1.x ; x<=tp2.x ; x++ ) - { - avg += m_relief[x+y*size]; - nb ++; - } - } - avg /= (float)nb; - - // Changes the description of the relief. - for ( y=tp1.y ; y<=tp2.y ; y++ ) - { - for ( x=tp1.x ; x<=tp2.x ; x++ ) - { - m_relief[x+y*size] = avg+height; - - if ( x%m_brick == 0 && y%m_depth != 0 ) - { - m_relief[(x+0)+(y-1)*size] = avg+height; - m_relief[(x+0)+(y+1)*size] = avg+height; - } - - if ( y%m_brick == 0 && x%m_depth != 0 ) - { - m_relief[(x-1)+(y+0)*size] = avg+height; - m_relief[(x+1)+(y+0)*size] = avg+height; - } - } - } - AdjustRelief(); - - pp1.x = (tp1.x-2)/m_brick; - pp1.y = (tp1.y-2)/m_brick; - pp2.x = (tp2.x+1)/m_brick; - pp2.y = (tp2.y+1)/m_brick; - - if ( pp1.x < 0 ) pp1.x = 0; - if ( pp1.x >= m_mosaic ) pp1.x = m_mosaic-1; - if ( pp1.y < 0 ) pp1.y = 0; - if ( pp1.y >= m_mosaic ) pp1.y = m_mosaic-1; - - for ( y=pp1.y ; y<=pp2.y ; y++ ) - { - for ( x=pp1.x ; x<=pp2.x ; x++ ) - { - m_engine->DeleteObject(m_objRank[x+y*m_mosaic]); - CreateSquare(m_bMultiText, x, y); // recreates the square - } - } - m_engine->Update(); - - return true; -} - - -// Management of the wind. - -void CTerrain::SetWind(Math::Vector speed) -{ - m_wind = speed; -} - -Math::Vector CTerrain::RetWind() -{ - return m_wind; -} - - -// Gives the exact slope of the terrain of a place given. - -float CTerrain::RetFineSlope(const Math::Vector &pos) -{ - Math::Vector n; - - if ( !GetNormal(n, pos) ) return 0.0f; - return fabs(Math::RotateAngle(Math::Point(n.x, n.z).Length(), n.y)-Math::PI/2.0f); -} - -// Gives the approximate slope of the terrain of a specific location. - -float CTerrain::RetCoarseSlope(const Math::Vector &pos) -{ - float dim, level[4], min, max; - int x, y; - - if ( m_relief == 0 ) return 0.0f; - - dim = (m_mosaic*m_brick*m_size)/2.0f; - - x = (int)((pos.x+dim)/m_size); - y = (int)((pos.z+dim)/m_size); - - if ( x < 0 || x >= m_mosaic*m_brick || - y < 0 || y >= m_mosaic*m_brick ) return 0.0f; - - level[0] = m_relief[(x+0)+(y+0)*(m_mosaic*m_brick+1)]; - level[1] = m_relief[(x+1)+(y+0)*(m_mosaic*m_brick+1)]; - level[2] = m_relief[(x+0)+(y+1)*(m_mosaic*m_brick+1)]; - level[3] = m_relief[(x+1)+(y+1)*(m_mosaic*m_brick+1)]; - - min = Math::Min(level[0], level[1], level[2], level[3]); - max = Math::Max(level[0], level[1], level[2], level[3]); - - return atanf((max-min)/m_size); -} - -// Gives the normal vector at the position p (x,-,z) of the ground. - -bool CTerrain::GetNormal(Math::Vector &n, const Math::Vector &p) -{ - Math::Vector p1, p2, p3, p4; - float dim; - int x, y; - - dim = (m_mosaic*m_brick*m_size)/2.0f; - - x = (int)((p.x+dim)/m_size); - y = (int)((p.z+dim)/m_size); - - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return false; - - p1 = RetVector(x+0, y+0); - p2 = RetVector(x+1, y+0); - p3 = RetVector(x+0, y+1); - p4 = RetVector(x+1, y+1); - - if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) ) - { - n = Math::NormalToPlane(p1,p2,p3); - } - else - { - n = Math::NormalToPlane(p2,p4,p3); - } - return true; -} - -// Returns the height of the ground. - -float CTerrain::RetFloorLevel(const Math::Vector &p, bool bBrut, bool bWater) -{ - Math::Vector p1, p2, p3, p4, ps; - float dim, level; - int x, y; - - dim = (m_mosaic*m_brick*m_size)/2.0f; - - x = (int)((p.x+dim)/m_size); - y = (int)((p.z+dim)/m_size); - - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return false; - - p1 = RetVector(x+0, y+0); - p2 = RetVector(x+1, y+0); - p3 = RetVector(x+0, y+1); - p4 = RetVector(x+1, y+1); - - ps = p; - if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) ) - { - if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f; - } - else - { - if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f; - } - - if ( !bBrut ) AdjustBuildingLevel(ps); - - if ( bWater ) // not going underwater? - { - level = m_water->RetLevel(); - if ( ps.y < level ) ps.y = level; // not under water - } - - return ps.y; -} - -// Returns the height to the ground. -// This height is positive when you are above the ground. - -float CTerrain::RetFloorHeight(const Math::Vector &p, bool bBrut, bool bWater) -{ - Math::Vector p1, p2, p3, p4, ps; - float dim, level; - int x, y; - - dim = (m_mosaic*m_brick*m_size)/2.0f; - - x = (int)((p.x+dim)/m_size); - y = (int)((p.z+dim)/m_size); - - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return false; - - p1 = RetVector(x+0, y+0); - p2 = RetVector(x+1, y+0); - p3 = RetVector(x+0, y+1); - p4 = RetVector(x+1, y+1); - - ps = p; - if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) ) - { - if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f; - } - else - { - if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f; - } - - if ( !bBrut ) AdjustBuildingLevel(ps); - - if ( bWater ) // not going underwater? - { - level = m_water->RetLevel(); - if ( ps.y < level ) ps.y = level; // not under water - } - - return p.y-ps.y; -} - -// Modifies the coordinate "y" of point "p" to rest on the ground floor. - -bool CTerrain::MoveOnFloor(Math::Vector &p, bool bBrut, bool bWater) -{ - Math::Vector p1, p2, p3, p4; - float dim, level; - int x, y; - - dim = (m_mosaic*m_brick*m_size)/2.0f; - - x = (int)((p.x+dim)/m_size); - y = (int)((p.z+dim)/m_size); - - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return false; - - p1 = RetVector(x+0, y+0); - p2 = RetVector(x+1, y+0); - p3 = RetVector(x+0, y+1); - p4 = RetVector(x+1, y+1); - - if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) ) - { - if ( !IntersectY(p1, p2, p3, p) ) return false; - } - else - { - if ( !IntersectY(p2, p4, p3, p) ) return false; - } - - if ( !bBrut ) AdjustBuildingLevel(p); - - if ( bWater ) // not going underwater? - { - level = m_water->RetLevel(); - if ( p.y < level ) p.y = level; // not under water - } - - return true; -} - -// Modifies a coordinate so that it is on the ground. -// Returns false if the initial coordinate was too far. - -bool CTerrain::ValidPosition(Math::Vector &p, float marging) -{ - bool bOK = true; - float limit; - - limit = m_mosaic*m_brick*m_size/2.0f - marging; - - if ( p.x < -limit ) - { - p.x = -limit; - bOK = false; - } - - if ( p.z < -limit ) - { - p.z = -limit; - bOK = false; - } - - if ( p.x > limit ) - { - p.x = limit; - bOK = false; - } - - if ( p.z > limit ) - { - p.z = limit; - bOK = false; - } - - return bOK; -} - - - -// Empty the table of elevations. - -void CTerrain::FlushBuildingLevel() -{ - m_buildingUsed = 0; -} - -// Adds a new elevation for a building. - -bool CTerrain::AddBuildingLevel(Math::Vector center, float min, float max, - float height, float factor) -{ - int i; - - for ( i=0 ; i= MAXBUILDINGLEVEL ) return false; - i = m_buildingUsed++; - - update: - m_buildingTable[i].center = center; - m_buildingTable[i].min = min; - m_buildingTable[i].max = max; - m_buildingTable[i].level = RetFloorLevel(center, true); - m_buildingTable[i].height = height; - m_buildingTable[i].factor = factor; - m_buildingTable[i].bboxMinX = center.x-max; - m_buildingTable[i].bboxMaxX = center.x+max; - m_buildingTable[i].bboxMinZ = center.z-max; - m_buildingTable[i].bboxMaxZ = center.z+max; - - return true; -} - -// Updates the elevation for a building when it was moved up (after a terraforming). - -bool CTerrain::UpdateBuildingLevel(Math::Vector center) -{ - int i; - - for ( i=0 ; i m_buildingTable[i].bboxMaxX || - p.z < m_buildingTable[i].bboxMinZ || - p.z > m_buildingTable[i].bboxMaxZ ) continue; - - dist = Math::DistanceProjected(p, m_buildingTable[i].center); - - if ( dist <= m_buildingTable[i].max ) - { - return m_buildingTable[i].factor; - } - } - return 1.0f; // it is normal on the ground -} - -// Adjusts a position according to a possible rise. - -void CTerrain::AdjustBuildingLevel(Math::Vector &p) -{ - Math::Vector border; - float dist, base; - int i; - - for ( i=0 ; i m_buildingTable[i].bboxMaxX || - p.z < m_buildingTable[i].bboxMinZ || - p.z > m_buildingTable[i].bboxMaxZ ) continue; - - dist = Math::DistanceProjected(p, m_buildingTable[i].center); - - if ( dist > m_buildingTable[i].max ) continue; - - if ( dist < m_buildingTable[i].min ) - { - p.y = m_buildingTable[i].level+m_buildingTable[i].height; - return; - } - -#if 0 - p.y = m_buildingTable[i].level; - p.y += (m_buildingTable[i].max-dist)/ - (m_buildingTable[i].max-m_buildingTable[i].min)* - m_buildingTable[i].height; - - base = RetFloorLevel(p, true); - if ( p.y < base ) p.y = base; -#else - border.x = ((p.x-m_buildingTable[i].center.x)*m_buildingTable[i].max)/ - dist+m_buildingTable[i].center.x; - border.z = ((p.z-m_buildingTable[i].center.z)*m_buildingTable[i].max)/ - dist+m_buildingTable[i].center.z; - - base = RetFloorLevel(border, true); - - p.y = (m_buildingTable[i].max-dist)/ - (m_buildingTable[i].max-m_buildingTable[i].min)* - (m_buildingTable[i].level+m_buildingTable[i].height-base)+ - base; -#endif - return; - } -} - - -// Returns the hardness of the ground in a given place. -// The hardness determines the noise (SOUND_STEP and SOUND_BOUM). - -float CTerrain::RetHardness(const Math::Vector &p) -{ - TerrainMaterial* tm; - float factor, dim; - int x, y, id; - - factor = RetBuildingFactor(p); - if ( factor != 1.0f ) return 1.0f; // on building - - if ( m_levelDot == 0 ) return m_defHardness; - - dim = (m_mosaic*m_brick*m_size)/2.0f; - - x = (int)((p.x+dim)/m_size); - y = (int)((p.z+dim)/m_size); - - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return m_defHardness; - - x /= m_brick/m_subdivMapping; - y /= m_brick/m_subdivMapping; - - if ( x < 0 || x >= m_levelDotSize || - y < 0 || y >= m_levelDotSize ) return m_defHardness; - - id = m_levelDot[x+y*m_levelDotSize].id; - tm = LevelSearchMat(id); - if ( tm == 0 ) return m_defHardness; - - return tm->hardness; -} - - -// Shows the flat areas on the ground. - -void CTerrain::GroundFlat(Math::Vector pos) -{ - Math::Vector p; - float rapport, angle; - int x, y, i; - static char table[41*41]; - - - rapport = 3200.0f/1024.0f; - - for ( y=0 ; y<=40 ; y++ ) - { - for ( x=0 ; x<=40 ; x++ ) - { - i = x + y*41; - table[i] = 0; - - p.x = (x-20)*rapport; - p.z = (y-20)*rapport; - p.y = 0.0f; - if ( Math::Point(p.x, p.y).Length() > 20.0f*rapport ) continue; - - angle = RetFineSlope(pos+p); - - if ( angle < FLATLIMIT ) - { - table[i] = 1; - } - else - { - table[i] = 2; - } - } - } - - m_engine->GroundMarkCreate(pos, 40.0f, 0.001f, 15.0f, 0.001f, 41, 41, table); -} - - -// Calculates the radius of the largest flat area available. -// This calculation is not optimized! - -float CTerrain::RetFlatZoneRadius(Math::Vector center, float max) -{ - Math::Vector pos; - Math::Point c, p; - float ref, radius, angle, h; - int i, nb; - - angle = RetFineSlope(center); - if ( angle >= FLATLIMIT ) return 0.0f; - - ref = RetFloorLevel(center, true); - - radius = 1.0f; - while ( radius <= max ) - { - angle = 0.0f; - nb = (int)(2.0f*Math::PI*radius); - if ( nb < 8 ) nb = 8; - for ( i=0 ; i 1.0f ) return radius; - - angle += Math::PI*2.0f/8.0f; - } - radius += 1.0f; - } - return max; -} - - - -// Specifies the maximum height of flight. - -void CTerrain::SetFlyingMaxHeight(float height) -{ - m_flyingMaxHeight = height; -} - -// Returns the maximum height of flight. - -float CTerrain::RetFlyingMaxHeight() -{ - return m_flyingMaxHeight; -} - - -// Empty the limits table of flight. - -void CTerrain::FlushFlyingLimit() -{ - m_flyingMaxHeight = 280.0f; - m_flyingLimitTotal = 0; -} - -// Empty the limits table of flight. - -bool CTerrain::AddFlyingLimit(Math::Vector center, - float extRadius, float intRadius, - float maxHeight) -{ - int i; - - if ( m_flyingLimitTotal >= MAXFLYINGLIMIT ) return false; - - i = m_flyingLimitTotal; - m_flyingLimit[i].center = center; - m_flyingLimit[i].extRadius = extRadius; - m_flyingLimit[i].intRadius = intRadius; - m_flyingLimit[i].maxHeight = maxHeight; - m_flyingLimitTotal = i+1; - - return true; -} - -// Returns the maximum height of flight. - -float CTerrain::RetFlyingLimit(Math::Vector pos, bool bNoLimit) -{ - float dist, h; - int i; - - if ( bNoLimit ) return 280.0f; - if ( m_flyingLimitTotal == 0 ) return m_flyingMaxHeight; - - for ( i=0 ; i= m_flyingLimit[i].extRadius ) continue; - - if ( dist <= m_flyingLimit[i].intRadius ) - { - return m_flyingLimit[i].maxHeight; - } - - dist -= m_flyingLimit[i].intRadius; - - h = dist*(m_flyingMaxHeight-m_flyingLimit[i].maxHeight)/ - (m_flyingLimit[i].extRadius-m_flyingLimit[i].intRadius); - - return h + m_flyingLimit[i].maxHeight; - } - - return m_flyingMaxHeight; -} - -- cgit v1.2.3-1-g7c22