summaryrefslogtreecommitdiffstats
path: root/src/old/terrain.cpp
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-06-26 23:39:31 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-06-26 23:39:31 +0200
commite738c55b73a8d635cac34fb3c37f3758ca4f1671 (patch)
tree3f12e1f4389bd676ce956baaf2dc841e311c3d2f /src/old/terrain.cpp
parentc2a7375788aea0cf1c0f4c45e4823a8a9a85264d (diff)
downloadcolobot-e738c55b73a8d635cac34fb3c37f3758ca4f1671.tar.gz
colobot-e738c55b73a8d635cac34fb3c37f3758ca4f1671.tar.bz2
colobot-e738c55b73a8d635cac34fb3c37f3758ca4f1671.zip
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
Diffstat (limited to 'src/old/terrain.cpp')
-rw-r--r--src/old/terrain.cpp2270
1 files changed, 0 insertions, 2270 deletions
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 <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#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<<brickP2;
- m_size = size;
- m_vision = vision;
- m_depth = depth;
- m_defHardness = hardness;
-
- m_engine->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<m_mosaic*m_subdivMapping ; y++ )
- {
- for ( x=0 ; x<m_mosaic*m_subdivMapping ; x++ )
- {
- m_texture[x+y*m_mosaic] = table[(x%dx)+(y%dy)*dx];
- }
- }
- return true;
-}
-
-
-// Empties level.
-
-void CTerrain::LevelFlush()
-{
- m_levelMatTotal = 0;
- m_levelMatMax = 0;
- m_levelID = 1000;
- LevelCloseTable();
-}
-
-// Initializes the names of textures to use for the land.
-
-bool CTerrain::LevelMaterial(int id, char* baseName, float u, float v,
- int up, int right, int down, int left,
- float hardness)
-{
- int i;
-
- i = m_levelMatTotal;
- if ( i >= 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<size ; y++ )
- {
- for ( x=0 ; x<size ; x++ )
- {
- level = (255-buffer[BMPHEAD+x+sizem*y])*scaleRelief;
-
-//? dist = Length((float)(x-size/2), (float)(y-size/2));
- dist = Math::Max(fabs((float)(x-size/2)), fabs((float)(y-size/2)));
- dist = dist/(float)(size/2);
- if ( dist > 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<m_mosaic*m_brick ; y+=b )
- {
- for ( x=0 ; x<m_mosaic*m_brick ; x+=b )
- {
- yy = 0;
- if ( (y+yy)%m_brick == 0 )
- {
- level1 = m_relief[(x+0)+(y+yy)*ii];
- level2 = m_relief[(x+b)+(y+yy)*ii];
- for ( xx=1 ; xx<b ; xx++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1;
- }
- }
-
- yy = b;
- if ( (y+yy)%m_brick == 0 )
- {
- level1 = m_relief[(x+0)+(y+yy)*ii];
- level2 = m_relief[(x+b)+(y+yy)*ii];
- for ( xx=1 ; xx<b ; xx++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1;
- }
- }
-
- xx = 0;
- if ( (x+xx)%m_brick == 0 )
- {
- level1 = m_relief[(x+xx)+(y+0)*ii];
- level2 = m_relief[(x+xx)+(y+b)*ii];
- for ( yy=1 ; yy<b ; yy++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1;
- }
- }
-
- xx = b;
- if ( (x+xx)%m_brick == 0 )
- {
- level1 = m_relief[(x+xx)+(y+0)*ii];
- level2 = m_relief[(x+xx)+(y+b)*ii];
- for ( yy=1 ; yy<b ; yy++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1;
- }
- }
- }
- }
-}
-
-
-// Calculates a vector of the terrain.
-
-Math::Vector CTerrain::RetVector(int x, int y)
-{
- Math::Vector p;
-
- p.x = x*m_size - (m_mosaic*m_brick*m_size)/2;
- p.z = y*m_size - (m_mosaic*m_brick*m_size)/2;
-
- if ( m_relief != 0 &&
- x >= 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 ; my<m_subdivMapping ; my++ )
- {
- for ( mx=0 ; mx<m_subdivMapping ; mx++ )
- {
- if ( m_bLevelText )
- {
- xx = ox*m_brick + mx*(m_brick/m_subdivMapping);
- yy = oy*m_brick + my*(m_brick/m_subdivMapping);
- LevelTextureName(xx, yy, texName1, uv);
- }
- else
- {
- i = (ox*m_subdivMapping+mx)+(oy*m_subdivMapping+my)*m_mosaic;
- sprintf(texName1, "%s%.3d%s", m_texBaseName, m_texture[i], m_texBaseExt);
- }
-
- for ( y=0 ; y<brick ; y+=step )
- {
- buffer = (D3DObjLevel6*)malloc(size);
- ZeroMemory(buffer, sizeof(D3DObjLevel6));
- buffer->totalPossible = 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 ; i<m_levelMatTotal ; i++ )
- {
- if ( id == m_levelMat[i].id )
- {
- return &m_levelMat[i];
- }
- }
-
- return 0;
-}
-
-// Chooses texture to use for a given square.
-
-void CTerrain::LevelTextureName(int x, int y, char *name, Math::Point &uv)
-{
- TerrainMaterial* tm;
-
- x /= m_brick/m_subdivMapping;
- y /= m_brick/m_subdivMapping;
-
- tm = LevelSearchMat(m_levelDot[x+y*m_levelDotSize].id);
- if ( tm == 0 )
- {
- strcpy(name, "xxx.tga");
- uv.x = 0.0f;
- uv.y = 0.0f;
- }
- else
- {
-//? sprintf(name, "%s.tga", tm->texName);
- 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 ; i<m_levelMatTotal ; i++ )
- {
- if ( m_levelMat[i].mat[0] == mat[0] &&
- m_levelMat[i].mat[1] == mat[1] &&
- m_levelMat[i].mat[2] == mat[2] &&
- m_levelMat[i].mat[3] == mat[3] ) return i;
- }
-
- return -1;
-}
-
-// Modifies the state of a point and its four neighbors, without testing if possible.
-
-void CTerrain::LevelSetDot(int x, int y, int id, char *mat)
-{
- TerrainMaterial* tm;
- int i, ii;
-
- tm = LevelSearchMat(id);
- if ( tm == 0 ) return;
-
- if ( tm->mat[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 ; up<m_levelMatMax ; up++ )
- {
- mat[0] = up;
- mat[1] = tm->mat[1];
- mat[2] = tm->mat[2];
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
-
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- mat[0] = tm->mat[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 ; down<m_levelMatMax ; down++ )
- {
- mat[0] = tm->mat[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 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = tm->mat[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 ; up<m_levelMatMax ; up++ )
- {
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- mat[0] = up;
- mat[1] = tm->mat[1];
- mat[2] = down;
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = right;
- mat[2] = tm->mat[2];
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- mat[0] = up;
- mat[1] = right;
- mat[2] = tm->mat[2];
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = right;
- mat[2] = down;
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = tm->mat[1];
- mat[2] = down;
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = up;
- mat[1] = tm->mat[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 ; up<m_levelMatMax ; up++ )
- {
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = up;
- mat[1] = right;
- mat[2] = down;
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
- }
- }
-
- OutputDebugString("LevelPutDot error\n");
- return false;
-}
-
-// Initializes all the ground with a material.
-
-bool CTerrain::LevelInit(int id)
-{
- TerrainMaterial* tm;
- int i, j;
-
- tm = LevelSearchMat(id);
- if ( tm == 0 ) return false;
-
- for ( i=0 ; i<m_levelDotSize*m_levelDotSize ; i++ )
- {
- m_levelDot[i].id = id;
-
- for ( j=0 ; j<4 ; j++ )
- {
- m_levelDot[i].mat[j] = tm->mat[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<m_levelDotSize ; y++ )
- {
- for ( x=0 ; x<m_levelDotSize ; x++ )
- {
- if ( radius != 0.0f )
- {
- pos.x = ((float)x-m_levelDotSize/2.0f)*group*m_size;
- pos.z = ((float)y-m_levelDotSize/2.0f)*group*m_size;
- if ( Math::DistanceProjected(pos, center) > 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 ; i<m_levelDotSize*m_levelDotSize ; i++ )
- {
- for ( j=0 ; j<4 ; j++ )
- {
- m_levelDot[i].mat[j] = 0;
- }
- }
-}
-
-// Closes the level table.
-
-void CTerrain::LevelCloseTable()
-{
- free(m_levelDot);
- m_levelDot = 0;
-}
-
-
-
-// Creates all objects in a mesh square ground.
-
-bool CTerrain::CreateSquare(bool bMultiRes, int x, int y)
-{
- D3DMATERIAL7 mat;
- float min, max;
- int step, objRank;
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- mat.diffuse.r = 1.0f;
- mat.diffuse.g = 1.0f;
- mat.diffuse.b = 1.0f;
- mat.ambient.r = 0.0f;
- mat.ambient.g = 0.0f;
- mat.ambient.b = 0.0f;
-
- objRank = m_engine->CreateObject();
- 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<m_depth ; step++ )
- {
- CreateMosaic(x, y, 1<<step, objRank, mat, min, max);
- min = max;
- max *= 2;
- if ( step == m_depth-1 ) max = g_HUGE;
- }
- }
- else
- {
- CreateMosaic(x, y, 1, objRank, mat, 0.0f, g_HUGE);
- }
-
- return true;
-}
-
-// Creates all objects of the terrain within the 3D engine.
-
-bool CTerrain::CreateObjects(bool bMultiRes)
-{
- int x, y;
-
- AdjustRelief();
-
- for ( y=0 ; y<m_mosaic ; y++ )
- {
- for ( x=0 ; x<m_mosaic ; x++ )
- {
- CreateSquare(bMultiRes, x, y);
- }
- }
-
- return true;
-}
-
-
-// Modifies the terrain's relief.
-// ATTENTION: ok only with m_depth = 2!
-
-bool CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, float height)
-{
- POINT tp1, tp2, pp1, pp2;
- float dim, avg;
- int x, y, size, nb;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
- tp1.x = (int)((p1.x+dim+m_size/2.0f)/m_size);
- tp1.y = (int)((p1.z+dim+m_size/2.0f)/m_size);
- tp2.x = (int)((p2.x+dim+m_size/2.0f)/m_size);
- tp2.y = (int)((p2.z+dim+m_size/2.0f)/m_size);
-
- if ( tp1.x > 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<m_buildingUsed ; i++ )
- {
- if ( center.x == m_buildingTable[i].center.x &&
- center.z == m_buildingTable[i].center.z )
- {
- goto update;
- }
- }
-
- if ( m_buildingUsed >= 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_buildingUsed ; i++ )
- {
- if ( center.x == m_buildingTable[i].center.x &&
- center.z == m_buildingTable[i].center.z )
- {
- m_buildingTable[i].center = center;
- m_buildingTable[i].level = RetFloorLevel(center, true);
- return true;
- }
- }
- return false;
-}
-
-// Removes the elevation for a building when it was destroyed.
-
-bool CTerrain::DeleteBuildingLevel(Math::Vector center)
-{
- int i, j;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( center.x == m_buildingTable[i].center.x &&
- center.z == m_buildingTable[i].center.z )
- {
- for ( j=i+1 ; j<m_buildingUsed ; j++ )
- {
- m_buildingTable[j-1] = m_buildingTable[j];
- }
- m_buildingUsed --;
- return true;
- }
- }
- return false;
-}
-
-// Returns the influence factor whether a position is on a possible rise.
-
-float CTerrain::RetBuildingFactor(const Math::Vector &p)
-{
- float dist;
- int i;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( p.x < m_buildingTable[i].bboxMinX ||
- p.x > 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_buildingUsed ; i++ )
- {
- if ( p.x < m_buildingTable[i].bboxMinX ||
- p.x > 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<nb ; i++ )
- {
- c.x = center.x;
- c.y = center.z;
- p.x = center.x+radius;
- p.y = center.z;
- p = Math::RotatePoint(c, angle, p);
- pos.x = p.x;
- pos.z = p.y;
- h = RetFloorLevel(pos, true);
- if ( fabs(h-ref) > 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_flyingLimitTotal ; i++ )
- {
- dist = Math::DistanceProjected(pos, m_flyingLimit[i].center);
-
- if ( dist >= 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;
-}
-