2021-11-15 20:58:13 -05:00
# include "world.h"
2021-12-03 11:49:59 -05:00
World : : World ( ) { }
2021-11-15 20:58:13 -05:00
2021-12-03 11:49:59 -05:00
World : : ~ World ( ) { }
2021-11-15 20:58:13 -05:00
Array2d < Chunk * > & World : : GetChunks ( ) { return m_chunks ; }
2021-11-15 21:39:50 -05:00
Chunk * World : : ChunkAt ( float x , float y , float z ) const {
2021-12-03 11:49:59 -05:00
int cx = ( int ) x / CHUNK_SIZE_X ;
int cz = ( int ) z / CHUNK_SIZE_Z ;
2021-11-15 21:39:50 -05:00
2021-12-03 11:49:59 -05:00
if ( x < 0 | | y < 0 | | z < 0 | |
x > = WORLD_SIZE_X * CHUNK_SIZE_X | |
z > = CHUNK_SIZE_Z * WORLD_SIZE_Y | |
y > CHUNK_SIZE_Y )
return 0 ;
2021-11-15 21:39:50 -05:00
2021-12-03 11:49:59 -05:00
return m_chunks . Get ( cx , cz ) ;
2021-11-15 21:39:50 -05:00
}
Chunk * World : : ChunkAt ( const Vector3f & pos ) const { return ChunkAt ( pos . x , pos . y , pos . z ) ; }
BlockType World : : BlockAt ( float x , float y , float z , BlockType defaultBlockType ) const {
2021-12-03 11:49:59 -05:00
Chunk * c = ChunkAt ( x , y , z ) ;
2021-11-15 21:39:50 -05:00
2021-12-03 11:49:59 -05:00
if ( ! c )
return defaultBlockType ;
2021-11-15 21:39:50 -05:00
2021-12-03 11:49:59 -05:00
int bx = ( int ) x % CHUNK_SIZE_X ;
int by = ( int ) y % CHUNK_SIZE_Y ;
int bz = ( int ) z % CHUNK_SIZE_Z ;
2021-11-15 21:39:50 -05:00
2021-12-03 11:49:59 -05:00
return c - > GetBlock ( bx , by , bz ) ;
2021-11-15 21:39:50 -05:00
}
BlockType World : : BlockAt ( const Vector3f & pos , BlockType defaultBlockType ) const {
2021-12-03 11:49:59 -05:00
return BlockAt ( pos . x , pos . y , pos . z , defaultBlockType ) ;
2021-11-15 21:39:50 -05:00
}
2021-11-30 19:55:11 -05:00
2021-12-01 21:21:45 -05:00
void World : : TransposeWorld ( Player & player ) {
2021-12-03 11:49:59 -05:00
int x = 0 ;
int y = 0 ;
if ( player . GetPosition ( ) . x > ( WORLD_SIZE_X * CHUNK_SIZE_X ) * .66f ) + + x ;
else if ( player . GetPosition ( ) . x < ( WORLD_SIZE_X * CHUNK_SIZE_X ) * .33f ) - - x ;
if ( player . GetPosition ( ) . z > ( WORLD_SIZE_Y * CHUNK_SIZE_Z ) * .66f ) + + y ;
else if ( player . GetPosition ( ) . z < ( WORLD_SIZE_Y * CHUNK_SIZE_Z ) * .33f ) - - y ;
if ( ! x & & ! y ) return ;
if ( x > 0 ) {
for ( int ax = 0 ; ax < WORLD_SIZE_X ; + + ax )
for ( int ay = 0 ; ay < WORLD_SIZE_Y ; + + ay )
if ( ax - x > = 0 )
m_chunks . Set ( ax - x , ay ,
m_chunks . Remove ( ax , ay ) ) ;
else if ( m_chunks . Get ( ax , ay ) ) m_tbDeleted . emplace_back ( m_chunks . Remove ( ax , ay ) ) ;
}
else if ( x < 0 ) {
for ( int ax = WORLD_SIZE_X - 1 ; ax > = 0 ; - - ax )
for ( int ay = WORLD_SIZE_Y - 1 ; ay > = 0 ; - - ay )
if ( ax - x < WORLD_SIZE_X )
m_chunks . Set ( ax - x , ay ,
m_chunks . Remove ( ax , ay ) ) ;
else if ( m_chunks . Get ( ax , ay ) ) m_tbDeleted . emplace_back ( m_chunks . Remove ( ax , ay ) ) ;
}
2021-12-01 22:06:47 -05:00
2021-12-03 11:49:59 -05:00
if ( y > 0 ) {
for ( int ax = 0 ; ax < WORLD_SIZE_X ; + + ax )
for ( int ay = 0 ; ay < WORLD_SIZE_Y ; + + ay )
if ( ay - y > = 0 )
m_chunks . Set ( ax , ay - y ,
m_chunks . Remove ( ax , ay ) ) ;
else if ( m_chunks . Get ( ax , ay ) ) m_tbDeleted . emplace_back ( m_chunks . Remove ( ax , ay ) ) ;
}
else if ( y < 0 ) {
for ( int ax = WORLD_SIZE_X - 1 ; ax > = 0 ; - - ax )
for ( int ay = WORLD_SIZE_Y - 1 ; ay > = 0 ; - - ay )
if ( ay - y < WORLD_SIZE_Y )
m_chunks . Set ( ax , ay - y ,
m_chunks . Remove ( ax , ay ) ) ;
else if ( m_chunks . Get ( ax , ay ) ) m_tbDeleted . emplace_back ( m_chunks . Remove ( ax , ay ) ) ;
}
2021-12-01 22:06:47 -05:00
2021-12-03 11:49:59 -05:00
m_center [ 0 ] + = x ; m_center [ 1 ] + = y ;
player . Teleport ( x , y ) ;
}
2021-12-01 22:06:47 -05:00
2021-12-03 11:49:59 -05:00
void World : : CleanUpWorld ( int & deleteframes , bool clear = false ) {
if ( clear ) {
while ( m_tbDeleted . size ( ) > 0 ) {
delete m_tbDeleted . back ( ) ;
m_tbDeleted . pop_back ( ) ;
}
}
if ( ! m_tbDeleted . empty ( ) & & ! deleteframes ) {
delete m_tbDeleted . back ( ) ;
m_tbDeleted . pop_back ( ) ;
deleteframes = FRAMES_DELETE_CHUNKS ;
}
2021-12-01 22:06:47 -05:00
}
2021-12-02 18:12:35 -05:00
void World : : GetScope ( int & x , int & y ) {
x = m_center [ 0 ] ;
y = m_center [ 1 ] ;
}
void World : : Update ( int & rendercount , int & badhitcount , Player & player , Transformation & world , Shader & shader , TextureAtlas & atlas , Perlin & perlin , BlockInfo * blockinfo [ BTYPE_LAST ] ) {
2021-12-06 11:08:34 -05:00
glStencilFunc ( GL_EQUAL , 1 , 0x00 ) ;
glStencilOp ( GL_KEEP , GL_KEEP , GL_REPLACE ) ;
2021-12-02 18:12:35 -05:00
atlas . Bind ( ) ;
RenderWorld ( rendercount , badhitcount , player , world , shader ) ;
2021-12-03 11:49:59 -05:00
TransposeWorld ( player ) ;
2021-12-02 18:12:35 -05:00
UpdateWorld ( player , perlin , blockinfo ) ;
shader . Disable ( ) ;
2021-12-06 11:08:34 -05:00
glStencilFunc ( GL_GREATER , 1 , 0xFF ) ;
2021-12-02 18:12:35 -05:00
}
bool World : : GenerateChunk ( int chx , int chy , Perlin & perlin ) {
2021-12-03 11:49:59 -05:00
2021-12-02 18:12:35 -05:00
if ( chx < WORLD_SIZE_X * CHUNK_SIZE_X & & chy < WORLD_SIZE_Y * CHUNK_SIZE_Z & &
chx > = 0 & & chy > = 0 )
if ( ! ChunkAt ( chx , 1 , chy ) ) {
for ( int index = 0 ; index < m_tbDeleted . size ( ) ; + + index ) { // V<> rifie l'existence d'un chunk dans le buffer de suppression avec sa position.
int x , y ;
2021-12-03 11:49:59 -05:00
2021-12-06 09:45:51 -05:00
if ( m_tbDeleted . at ( index ) ) {
2021-12-03 11:49:59 -05:00
m_tbDeleted . at ( index ) - > GetPosition ( x , y ) ;
if ( chx / CHUNK_SIZE_X + m_center [ 0 ] = = x & &
2021-12-02 18:12:35 -05:00
chy / CHUNK_SIZE_Z + m_center [ 1 ] = = y ) {
GetChunks ( ) . Set ( chx / CHUNK_SIZE_X , chy / CHUNK_SIZE_Z , std : : move ( m_tbDeleted . at ( index ) ) ) ;
return true ;
}
2021-12-03 11:49:59 -05:00
}
2021-12-02 18:12:35 -05:00
}
std : : ostringstream pos ; // V<> rifie l'existence d'un fichier .chunk avec sa position.
pos < < CHUNK_PATH < < chx / CHUNK_SIZE_X + m_center [ 0 ] < < ' _ ' < < chy / CHUNK_SIZE_Z + m_center [ 1 ] < < " .chunk " ;
std : : ifstream input ( pos . str ( ) . c_str ( ) , std : : fstream : : binary ) ;
if ( input . fail ( ) ) {
GetChunks ( ) . Set ( chx / CHUNK_SIZE_X , chy / CHUNK_SIZE_Z , new Chunk ( chx / CHUNK_SIZE_X + m_center [ 0 ] , chy / CHUNK_SIZE_Z + m_center [ 1 ] ) ) ;
Chunk * chunk = GetChunks ( ) . Get ( chx / CHUNK_SIZE_X , chy / CHUNK_SIZE_Z ) ;
2021-12-06 09:45:51 -05:00
for ( int x = 0 ; x < CHUNK_SIZE_X ; + + x ) // Montagnes
2021-12-02 18:12:35 -05:00
for ( int z = 0 ; z < CHUNK_SIZE_Z ; + + z ) {
2021-12-03 11:49:59 -05:00
float xnoiz , ynoiz ;
xnoiz = ( double ) ( x + ( chx / CHUNK_SIZE_X + m_center [ 0 ] ) * CHUNK_SIZE_X ) / ( double ) INT16_MAX ;
ynoiz = ( double ) ( z + ( chy / CHUNK_SIZE_Z + m_center [ 1 ] ) * CHUNK_SIZE_Z ) / ( double ) INT16_MAX ;
2021-12-04 09:55:43 -05:00
float height = ( perlin . Get ( xnoiz , ynoiz ) ) * 20.f + 5.f ;
for ( int y = 0 ; y < = ( int ) height % CHUNK_SIZE_Y ; + + y )
2021-12-02 18:12:35 -05:00
chunk - > SetBlock ( x , y , z , BTYPE_METAL , this ) ;
}
2021-12-06 09:45:51 -05:00
for ( int x = 0 ; x < CHUNK_SIZE_X ; + + x ) // Collines
2021-12-02 18:12:35 -05:00
for ( int z = 0 ; z < CHUNK_SIZE_Z ; + + z ) {
2021-12-03 11:49:59 -05:00
float xnoiz , ynoiz ;
xnoiz = ( double ) ( x + ( chx / CHUNK_SIZE_X + m_center [ 0 ] ) * CHUNK_SIZE_X ) / ( double ) INT16_MAX ;
ynoiz = ( double ) ( z + ( chy / CHUNK_SIZE_Z + m_center [ 1 ] ) * CHUNK_SIZE_Z ) / ( double ) INT16_MAX ;
2021-12-06 09:45:51 -05:00
float height = perlin . Get ( xnoiz , ynoiz ) * 5.f + 24.f ;
2021-12-02 18:12:35 -05:00
for ( int y = 0 ; y < = ( int ) height % CHUNK_SIZE_Y ; + + y ) {
if ( chunk - > GetBlock ( x , y , z ) = = BTYPE_AIR )
chunk - > SetBlock ( x , y , z , BTYPE_GRASS , this ) ;
}
}
2021-12-06 09:45:51 -05:00
for ( int x = 0 ; x < CHUNK_SIZE_X ; + + x ) // "Lacs"
2021-12-02 18:12:35 -05:00
for ( int z = 0 ; z < CHUNK_SIZE_Z ; + + z ) {
2021-12-06 10:58:40 -05:00
for ( int y = 0 ; y < 13 ; + + y ) {
2021-12-02 18:12:35 -05:00
if ( chunk - > GetBlock ( x , y , z ) = = BTYPE_AIR )
chunk - > SetBlock ( x , y , z , BTYPE_ICE , this ) ;
}
}
2021-12-06 09:45:51 -05:00
for ( int x = 0 ; x < CHUNK_SIZE_X ; + + x ) // "Arbres"
for ( int z = 0 ; z < CHUNK_SIZE_Z ; + + z ) {
float xnoiz , ynoiz ;
xnoiz = ( double ) ( z * CHUNK_SIZE_Y + ( chx / CHUNK_SIZE_X + m_center [ 0 ] ) * CHUNK_SIZE_X ) / ( double ) INT16_MAX ;
ynoiz = ( double ) ( x * CHUNK_SIZE_Y + ( chy / CHUNK_SIZE_Z + m_center [ 1 ] ) * CHUNK_SIZE_Z ) / ( double ) INT16_MAX ;
bool tree = ( int ) ( abs ( perlin . Get ( xnoiz , ynoiz ) ) * 17933.f ) % CHUNK_SIZE_Y > 126 ? true : false ;
for ( int y = 0 ; y < CHUNK_SIZE_Y - 10 ; + + y )
if ( chunk - > GetBlock ( x , y , z ) = = BTYPE_AIR )
if ( chunk - > GetBlock ( x , y - 1 , z ) = = BTYPE_GRASS )
if ( tree ) {
for ( int i = 0 ; i < ( int ) ( abs ( perlin . Get ( xnoiz , ynoiz ) ) ) % 3 + 1 ; + + i )
chunk - > SetBlock ( x , y + i , z , BTYPE_DIRT , this ) ;
break ;
}
}
2021-12-02 18:12:35 -05:00
}
else {
input . seekg ( 0 , std : : ios_base : : end ) ;
int size = input . tellg ( ) ;
input . seekg ( 0 , std : : ios_base : : beg ) ;
char * data = new char [ size ] ;
input . read ( data , size ) ;
input . close ( ) ;
GetChunks ( ) . Set ( chx / CHUNK_SIZE_X , chy / CHUNK_SIZE_Z , new Chunk ( chx / CHUNK_SIZE_X + m_center [ 0 ] , chy / CHUNK_SIZE_Z + m_center [ 1 ] , data ) ) ;
delete [ ] data ;
}
return true ;
}
return false ;
}
void World : : UpdateChunk ( int & generates , int & updates , int chx , int chy , Perlin & perlin , BlockInfo * blockinfo [ BTYPE_LAST ] ) {
if ( generates = = 0 & & GenerateChunk ( chx , chy , perlin ) ) generates = FRAMES_RENDER_CHUNKS ;
if ( updates = = 0 & & ChunkAt ( chx , 1 , chy ) & &
ChunkAt ( chx , 1 , chy ) - > IsDirty ( ) ) {
ChunkAt ( chx , 1 , chy ) - > Update ( blockinfo , this ) ;
updates = FRAMES_UPDATE_CHUNKS ;
}
}
void World : : ChangeBlockAtCursor ( BlockType blockType , Player & player , bool & block ) {
Vector3f currentPos = player . GetPosition ( ) ;
Vector3f currentBlock = currentPos ;
Vector3f ray = player . GetDirection ( ) ;
bool found = false ;
if ( block ) return ;
while ( ( currentPos - currentBlock ) . Length ( ) < = MAX_SELECTION_DISTANCE & & ! found ) {
currentBlock + = ray / 10.f ;
BlockType bt = BlockAt ( currentBlock ) ;
if ( bt ! = BTYPE_AIR )
found = true ;
}
if ( found )
if ( blockType ! = BTYPE_AIR ) {
found = false ;
while ( ( currentPos - currentBlock ) . Length ( ) > = 1.7f & & ! found ) {
currentBlock - = ray / 10.f ;
BlockType bt = BlockAt ( currentBlock ) ;
if ( bt = = BTYPE_AIR ) { // V<> rification pour <20> tre s<> r que le bloc <20> changer n'est pas dans le joueur.
int Bx = ( int ) currentBlock . x ;
int By = ( int ) currentBlock . y ;
int Bz = ( int ) currentBlock . z ;
int Px = ( int ) currentPos . x ;
int PyA = ( int ) currentPos . y ;
int PyB = ( int ) ( currentPos . y - .9f ) ;
int PyC = ( int ) ( currentPos . y - 1.7f ) ;
int Pz = ( int ) currentPos . z ;
if ( ! ( Bx = = Px & &
( By = = PyA | |
By = = PyB | |
By = = PyC ) & &
Bz = = Pz ) )
found = true ;
}
}
}
if ( found & & ( int ) currentBlock . y < CHUNK_SIZE_Y ) {
int bx = ( int ) currentBlock . x % CHUNK_SIZE_X ;
int by = ( int ) currentBlock . y % CHUNK_SIZE_Y ;
int bz = ( int ) currentBlock . z % CHUNK_SIZE_Z ;
ChunkAt ( currentBlock ) - > SetBlock ( bx , by , bz , blockType , this ) ;
ChunkAt ( currentBlock ) - > MakeModified ( ) ;
block = true ;
}
}
void World : : RenderWorld ( int & rendercount , int & badhitcount , Player & player , Transformation & world , Shader & shader ) {
shader . Use ( ) ;
rendercount = 0 ;
badhitcount = 0 ;
Vector3f angle ;
Vector3f cursor ;
Vector3f direct = player . GetDirection ( ) ;
Vector3f pos = player . GetPosition ( ) - direct ;
direct . y = 0 ;
direct . Normalize ( ) ;
pos . y = 1 ;
2021-12-03 11:49:59 -05:00
2021-12-04 09:55:43 -05:00
static Vector3f renderManifest [ VIEW_DISTANCE * 4 ] ;
2021-12-02 18:12:35 -05:00
2021-12-06 09:45:51 -05:00
//for (int dist = VIEW_DISTANCE; dist >= 0; dist -= CHUNK_SIZE_X) {
for ( int dist = 0 ; dist < = VIEW_DISTANCE ; dist + = CHUNK_SIZE_X ) {
2021-12-02 18:12:35 -05:00
// Configuration du radar.
2021-12-03 11:49:59 -05:00
float sinus , cosinus ;
int echantillons ;
2021-12-06 09:45:51 -05:00
2021-12-04 09:55:43 -05:00
if ( dist > VIEW_DISTANCE * .625f ) {
2021-12-03 11:49:59 -05:00
sinus = .01745240643 ; // sin(1 degr<67> )
cosinus = .99984769515 ; // cos(1 degr<67> )
echantillons = 90 ;
}
2021-12-06 09:45:51 -05:00
else if ( dist > VIEW_DISTANCE * .325f ) {
2021-12-03 11:49:59 -05:00
sinus = .0261769483 ;
cosinus = .99965732497 ;
echantillons = 60 ;
}
2021-12-06 09:45:51 -05:00
else {
2021-12-03 11:49:59 -05:00
sinus = .0348994967 ;
cosinus = .99939082701 ;
echantillons = 45 ;
}
2021-12-03 11:53:53 -05:00
angle . x = direct . z + direct . x ;
angle . z = direct . z - direct . x ;
2021-12-02 18:12:35 -05:00
angle . y = 0 ;
angle . Normalize ( ) ;
for ( int radar = 0 ; radar < echantillons ; + + radar ) {
float x = angle . x ;
2021-12-03 11:51:59 -05:00
angle . x = angle . x * cosinus - angle . z * sinus ;
angle . z = angle . z * cosinus + x * sinus ;
2021-12-02 18:12:35 -05:00
angle . Normalize ( ) ;
cursor = pos - direct * CHUNK_SIZE_X * 2 + angle * dist ;
2021-12-04 09:55:43 -05:00
if ( cursor . y > = 128.f | | cursor . y > = 0.f ) cursor . y = CHUNK_SIZE_Y / 2.f ;
2021-12-02 18:12:35 -05:00
bool valide = true ;
if ( ChunkAt ( cursor ) ) {
int chx , chy ;
ChunkAt ( cursor ) - > GetPosition ( chx , chy ) ;
2021-12-03 11:53:05 -05:00
for ( int index = 0 ; index < rendercount ; + + index ) // Permet de v<> rifier seulement contre celles ajout<75> es dans la frame, et ne pas avoir <20> refaire l'array <20> chaque frame.
2021-12-04 09:55:43 -05:00
if ( renderManifest [ index ] . x = = chx & & renderManifest [ index ] . z = = chy ) {
2021-12-02 18:12:35 -05:00
valide = false ;
+ + badhitcount ;
}
2021-12-06 09:45:51 -05:00
if ( valide ) renderManifest [ rendercount + + ] = Vector3f ( chx , ( VIEW_DISTANCE - ( pos - cursor ) . Length ( ) * 2.f + 128 ) / ( float ) VIEW_DISTANCE , chy ) ;
2021-12-02 18:12:35 -05:00
}
}
}
2021-12-04 09:55:43 -05:00
for ( int index = 0 ; index < rendercount ; + + index ) {
int chx = ( renderManifest [ index ] . x - m_center [ 0 ] ) * CHUNK_SIZE_X , chy = ( renderManifest [ index ] . z - m_center [ 1 ] ) * CHUNK_SIZE_Z ;
world . ApplyTranslation ( chx , 0 , chy ) ;
world . Use ( ) ;
2021-12-06 09:45:51 -05:00
glBlendColor ( renderManifest [ index ] . y , renderManifest [ index ] . y , renderManifest [ index ] . y , 1.f ) ;
2021-12-04 09:55:43 -05:00
ChunkAt ( chx , 1 , chy ) - > Render ( ) ;
world . ApplyTranslation ( - chx , 0 , - chy ) ;
}
2021-12-02 18:12:35 -05:00
shader . Disable ( ) ;
} ;
void World : : UpdateWorld ( Player & player , Perlin & perlin , BlockInfo * blockinfo [ BTYPE_LAST ] ) {
int cx = player . GetPosition ( ) . x ;
int cy = player . GetPosition ( ) . z ;
static int frameGenerate = 0 ;
static int frameUpdate = 0 ;
static int frameDelete = 0 ;
int side = 0 ;
if ( frameGenerate > 0 ) - - frameGenerate ;
if ( frameUpdate > 0 ) - - frameUpdate ;
if ( frameDelete > 0 ) - - frameDelete ;
if ( ! frameGenerate | | ! frameUpdate )
while ( side * CHUNK_SIZE_X < = VIEW_DISTANCE * 2 ) {
int tx = - side , ty = - side ;
for ( ; tx < = side ; + + tx )
UpdateChunk ( frameGenerate , frameUpdate , cx + tx * CHUNK_SIZE_X , cy + ty * CHUNK_SIZE_Z , perlin , blockinfo ) ;
for ( ; ty < = side ; + + ty )
UpdateChunk ( frameGenerate , frameUpdate , cx + tx * CHUNK_SIZE_X , cy + ty * CHUNK_SIZE_Z , perlin , blockinfo ) ;
for ( ; tx > = - side ; - - tx )
UpdateChunk ( frameGenerate , frameUpdate , cx + tx * CHUNK_SIZE_X , cy + ty * CHUNK_SIZE_Z , perlin , blockinfo ) ;
for ( ; ty > = - side ; - - ty )
UpdateChunk ( frameGenerate , frameUpdate , cx + tx * CHUNK_SIZE_X , cy + ty * CHUNK_SIZE_Z , perlin , blockinfo ) ;
+ + side ;
}
CleanUpWorld ( frameDelete ) ;
}