2021-09-24 10:15:43 -04:00
# include "engine.h"
# include <algorithm>
# include <cmath>
2021-09-27 11:30:18 -04:00
# include "transformation.h"
2021-09-27 13:15:57 -04:00
# include "player.h"
2021-09-24 10:15:43 -04:00
2021-09-27 11:30:18 -04:00
Engine : : Engine ( ) { }
2021-09-24 10:15:43 -04:00
2021-09-27 11:30:18 -04:00
Engine : : ~ Engine ( ) { }
2021-09-24 10:15:43 -04:00
void Engine : : Init ( )
{
2021-10-11 11:37:58 -04:00
GLenum glewErr = glewInit ( ) ;
2021-10-12 15:58:54 -04:00
if ( glewErr ! = GLEW_OK ) {
2021-10-11 11:37:58 -04:00
std : : cerr < < " ERREUR GLEW : " < < glewGetErrorString ( glewErr ) < < std : : endl ;
abort ( ) ;
}
2021-09-27 10:20:58 -04:00
glClearColor ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
glEnable ( GL_TEXTURE_2D ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
gluPerspective ( 45.0f , ( float ) Width ( ) / ( float ) Height ( ) , 0.0001f , 1000.0f ) ;
glEnable ( GL_DEPTH_TEST ) ;
glHint ( GL_PERSPECTIVE_CORRECTION_HINT , GL_NICEST ) ;
glShadeModel ( GL_SMOOTH ) ;
glEnable ( GL_LIGHTING ) ;
glEnable ( GL_LINE_SMOOTH ) ;
2021-10-06 21:32:12 -04:00
glEnable ( GL_CULL_FACE ) ;
2021-09-27 10:20:58 -04:00
// Light
2021-11-19 08:35:19 -05:00
GLfloat light0Pos [ 4 ] = { 0.0f , CHUNK_SIZE_Y , 0.0f , 1.0f } ;
2021-10-25 10:50:08 -04:00
GLfloat light0Amb [ 4 ] = { 0.2f , 0.2f , 0.2f , 1.f } ;
2021-09-27 14:45:59 -04:00
GLfloat light0Diff [ 4 ] = { 1.f , 1.f , 1.f , 1.f } ;
2021-09-27 10:20:58 -04:00
GLfloat light0Spec [ 4 ] = { 0.2f , 0.2f , 0.2f , 1.0f } ;
glEnable ( GL_LIGHT0 ) ;
glLightfv ( GL_LIGHT0 , GL_POSITION , light0Pos ) ;
glLightfv ( GL_LIGHT0 , GL_AMBIENT , light0Amb ) ;
glLightfv ( GL_LIGHT0 , GL_DIFFUSE , light0Diff ) ;
2021-11-19 08:35:19 -05:00
glLightfv ( GL_LIGHT0 , GL_SPECULAR , light0Spec ) ;
2021-09-27 10:20:58 -04:00
2021-10-12 15:58:54 -04:00
// Objet de skybox avec sa propre texture et son propre shader!
m_skybox . Init ( 0.00013f ) ;
2021-10-04 12:29:10 -04:00
2021-10-19 10:27:59 -04:00
// Objet de musique!
2021-11-15 20:58:13 -05:00
m_audio . ToggleMusicState ( ) ;
2021-11-16 20:48:52 -05:00
// Init Chunks
2021-11-19 11:11:08 -05:00
m_world . GetChunks ( ) . Reset ( nullptr ) ;
2021-11-02 18:01:06 -04:00
2021-10-31 00:31:08 -04:00
// Gestion de souris.
2021-09-27 10:20:58 -04:00
CenterMouse ( ) ;
HideCursor ( ) ;
2021-09-24 10:15:43 -04:00
}
2021-09-27 11:30:18 -04:00
void Engine : : DeInit ( ) { }
2021-09-24 10:15:43 -04:00
2021-09-27 11:30:18 -04:00
void Engine : : LoadResource ( ) {
2021-10-02 15:00:48 -04:00
LoadTexture ( m_textureFloor , TEXTURE_PATH " grass.png " ) ;
2021-10-12 15:58:54 -04:00
LoadTexture ( m_skybox . GetTexture ( ) , TEXTURE_PATH " skybox.png " ) ;
2021-10-26 17:28:37 -04:00
LoadTexture ( m_textureCrosshair , TEXTURE_PATH " cross.bmp " ) ;
LoadTexture ( m_textureFont , TEXTURE_PATH " font.bmp " ) ;
2021-10-31 00:31:08 -04:00
TextureAtlas : : TextureIndex texDirtIndex = m_textureAtlas . AddTexture ( TEXTURE_PATH " metal3.png " ) ;
TextureAtlas : : TextureIndex texIceIndex = m_textureAtlas . AddTexture ( TEXTURE_PATH " dirt.png " ) ;
TextureAtlas : : TextureIndex texGrassIndex = m_textureAtlas . AddTexture ( TEXTURE_PATH " grass.png " ) ;
TextureAtlas : : TextureIndex texMetalIndex = m_textureAtlas . AddTexture ( TEXTURE_PATH " metal.png " ) ;
2021-10-26 17:28:37 -04:00
2021-11-26 11:59:02 -05:00
if ( ! m_textureAtlas . Generate ( 128 , false ) ) {
2021-10-26 17:28:37 -04:00
std : : cout < < " Unable to generate texture atlas ... " < < std : : endl ;
abort ( ) ;
}
2021-10-11 11:37:58 -04:00
2021-10-31 00:31:08 -04:00
float u , v , s ;
m_textureAtlas . TextureIndexToCoord ( texDirtIndex , u , v , s , s ) ;
m_blockinfo [ BTYPE_DIRT ] = new BlockInfo ( BTYPE_DIRT , " Dirt " , u , v , s , 1 ) ;
m_textureAtlas . TextureIndexToCoord ( texGrassIndex , u , v , s , s ) ;
m_blockinfo [ BTYPE_GRASS ] = new BlockInfo ( BTYPE_GRASS , " Grass " , u , v , s , 1 ) ;
m_textureAtlas . TextureIndexToCoord ( texMetalIndex , u , v , s , s ) ;
m_blockinfo [ BTYPE_METAL ] = new BlockInfo ( BTYPE_METAL , " Metal " , u , v , s , 1 ) ;
m_textureAtlas . TextureIndexToCoord ( texIceIndex , u , v , s , s ) ;
m_blockinfo [ BTYPE_ICE ] = new BlockInfo ( BTYPE_ICE , " Ice " , u , v , s , 1 ) ;
2021-10-11 11:37:58 -04:00
std : : cout < < " Loading and compiling shaders ... " < < std : : endl ;
2021-10-12 15:58:54 -04:00
if ( ! m_shader01 . Load ( SHADER_PATH " shader01.vert " , SHADER_PATH " shader01.frag " , true ) ) {
2021-10-11 11:37:58 -04:00
std : : cout < < " Failed to load shader " < < std : : endl ;
exit ( 1 ) ;
}
2021-09-24 10:15:43 -04:00
2021-10-12 15:58:54 -04:00
if ( ! m_skybox . GetShader ( ) . Load ( SHADER_PATH " skybox.vert " , SHADER_PATH " skybox.frag " , true ) ) {
std : : cout < < " Failed to load shader " < < std : : endl ;
exit ( 1 ) ;
}
2021-09-24 10:15:43 -04:00
}
2021-11-15 20:58:13 -05:00
void Engine : : UnloadResource ( ) { }
2021-10-12 15:58:54 -04:00
2021-10-26 17:28:37 -04:00
void Engine : : DrawHud ( float elapsedTime ) {
// Setter le blend function , tout ce qui sera noir sera transparent
glDisable ( GL_LIGHTING ) ;
glColor4f ( 1.f , 1.f , 1.f , 1.f ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE ) ;
glEnable ( GL_BLEND ) ;
glDisable ( GL_DEPTH_TEST ) ;
glMatrixMode ( GL_PROJECTION ) ;
glPushMatrix ( ) ;
glLoadIdentity ( ) ;
glOrtho ( 0 , Width ( ) , 0 , Height ( ) , - 1 , 1 ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glPushMatrix ( ) ;
// Bind de la texture pour le font
m_textureFont . Bind ( ) ;
std : : ostringstream ss ;
ss < < " Fps : " < < GetFps ( elapsedTime ) ;
PrintText ( 10 , Height ( ) - 25 , ss . str ( ) ) ;
ss . str ( " " ) ;
2021-11-26 11:59:02 -05:00
ss < < " Rendered Chunks : " < < m_renderCount ;
PrintText ( 10 , Height ( ) - 35 , ss . str ( ) ) ;
ss . str ( " " ) ;
2021-10-26 17:28:37 -04:00
ss < < " Velocity : " < < m_player . GetVelocity ( ) ; // IMPORTANT : on utilise l <20> operateur << pour afficher la position
PrintText ( 10 , 10 , ss . str ( ) ) ;
ss . str ( " " ) ;
ss < < " Direction : " < < m_player . GetDirection ( ) ;
PrintText ( 10 , 20 , ss . str ( ) ) ;
ss . str ( " " ) ;
ss < < " Position : " < < m_player . GetPosition ( ) ;
PrintText ( 10 , 30 , ss . str ( ) ) ;
2021-11-15 20:58:13 -05:00
ss . str ( " " ) ;
2021-11-16 20:48:52 -05:00
ss < < " CamPos : " < < m_player . GetPOV ( ) ;
2021-11-15 20:58:13 -05:00
PrintText ( 10 , 40 , ss . str ( ) ) ;
2021-10-26 17:28:37 -04:00
// Affichage du crosshair
m_textureCrosshair . Bind ( ) ;
static const int crossSize = 32 ;
glLoadIdentity ( ) ;
glTranslated ( Width ( ) / 2 - crossSize / 2 , Height ( ) / 2 - crossSize / 2 , 0 ) ;
glBegin ( GL_QUADS ) ;
2021-11-15 20:58:13 -05:00
glTexCoord2f ( 0 , 0 ) ;
2021-10-26 17:28:37 -04:00
glVertex2i ( 0 , 0 ) ;
glTexCoord2f ( 1 , 0 ) ;
glVertex2i ( crossSize , 0 ) ;
glTexCoord2f ( 1 , 1 ) ;
glVertex2i ( crossSize , crossSize ) ;
glTexCoord2f ( 0 , 1 ) ;
glVertex2i ( 0 , crossSize ) ;
glEnd ( ) ;
glEnable ( GL_LIGHTING ) ;
glDisable ( GL_BLEND ) ;
glEnable ( GL_DEPTH_TEST ) ;
glMatrixMode ( GL_PROJECTION ) ;
glPopMatrix ( ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glPopMatrix ( ) ;
}
void Engine : : PrintText ( unsigned int x , unsigned int y , const std : : string & t ) {
glLoadIdentity ( ) ;
glTranslated ( x , y , 0 ) ;
for ( unsigned int i = 0 ; i < t . length ( ) ; + + i ) {
float left = ( float ) ( ( t [ i ] - 32 ) % 16 ) / 16.f ;
float top = ( float ) ( ( t [ i ] - 32 ) / 16 ) / 16.f ;
top + = .5f ;
glBegin ( GL_QUADS ) ;
glTexCoord2f ( left , 1.f - top - .0625f ) ;
glVertex2f ( 0 , 0 ) ;
glTexCoord2f ( left + .0625f , 1.f - top - .0625f ) ;
glVertex2f ( 12 , 0 ) ;
glTexCoord2f ( left + .0625f , 1.f - top ) ;
glVertex2f ( 12 , 12 ) ;
glTexCoord2f ( left , 1.f - top ) ;
glVertex2f ( 0 , 12 ) ;
glEnd ( ) ;
glTranslated ( 8 , 0 , 0 ) ;
}
}
int Engine : : GetFps ( float elapsedTime ) const { return 1 / elapsedTime ; }
void Engine : : Render ( float elapsedTime ) {
2021-09-27 10:20:58 -04:00
static float gameTime = elapsedTime ;
2021-11-15 20:58:13 -05:00
if ( elapsedTime > 0.1f ) return ;
2021-09-27 10:20:58 -04:00
gameTime + = elapsedTime ;
2021-09-27 13:15:57 -04:00
Transformation all ;
2021-09-27 13:56:29 -04:00
Transformation skybox ;
2021-09-27 10:20:58 -04:00
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
// Transformations initiales
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
2021-11-15 20:58:13 -05:00
m_player . ApplyPhysics ( m_player . GetInput ( m_keyW , m_keyS , m_keyA , m_keyD , m_keySpace , m_keylshift , elapsedTime ) , m_world , elapsedTime ) ;
2021-11-19 08:35:19 -05:00
m_audio . Update3DAudio ( m_player . GetPOV ( ) , m_player . GetDirection ( ) , m_player . GetVelocity ( ) ) ; // Ajustement du positionnement 3D avec les coordonn<6E> es du joueur et
2021-10-26 17:28:37 -04:00
// son vecteur de v<> locit<69> (pour l'effet Doppler)
2021-09-27 13:15:57 -04:00
m_player . ApplyTransformation ( all ) ;
2021-11-19 13:25:52 -05:00
2021-10-06 21:33:56 -04:00
m_player . ApplyTransformation ( skybox , false ) ; // Version d'ApplyTransformation qui ne tient compte que de la rotation
// (donc l'objet ne bouge pas relativement au joueur, ce qui est pratique pour une skybox!).
2021-10-25 10:50:08 -04:00
glDisable ( GL_LIGHT0 ) ;
2021-10-12 15:58:54 -04:00
m_skybox . Render ( skybox ) ;
2021-10-25 10:50:08 -04:00
2021-11-26 11:59:02 -05:00
// G<> n<EFBFBD> ration/Update de Chunks.
glEnable ( GL_LIGHT0 ) ;
m_textureAtlas . Bind ( ) ;
int cx = m_player . GetPosition ( ) . x ;
int cy = m_player . GetPosition ( ) . z ;
static int frameGenerate = 0 ;
static int frameUpdate = 0 ;
int side = 0 ;
m_shader01 . Use ( ) ;
m_renderCount = 0 ;
2021-11-19 13:25:52 -05:00
2021-11-26 11:59:02 -05:00
if ( frameGenerate > 0 ) - - frameGenerate ;
if ( frameUpdate > 0 ) - - frameUpdate ;
if ( ! frameGenerate | | ! frameUpdate )
while ( side * CHUNK_SIZE_X < = VIEW_DISTANCE ) {
int tx = - side , ty = - side ;
for ( ; tx < = side ; + + tx )
UpdateWorld ( frameGenerate , frameUpdate , cx + tx * CHUNK_SIZE_X , cy + ty * CHUNK_SIZE_Z ) ;
for ( ; ty < = side ; + + ty )
UpdateWorld ( frameGenerate , frameUpdate , cx + tx * CHUNK_SIZE_X , cy + ty * CHUNK_SIZE_Z ) ;
for ( ; tx > = - side ; - - tx )
UpdateWorld ( frameGenerate , frameUpdate , cx + tx * CHUNK_SIZE_X , cy + ty * CHUNK_SIZE_Z ) ;
for ( ; ty > = - side ; - - ty )
UpdateWorld ( frameGenerate , frameUpdate , cx + tx * CHUNK_SIZE_X , cy + ty * CHUNK_SIZE_Z ) ;
2021-11-19 13:25:52 -05:00
2021-11-26 11:59:02 -05:00
+ + side ;
}
2021-11-19 13:25:52 -05:00
2021-11-26 11:59:02 -05:00
// Rendering de Chunks.
2021-10-04 12:29:10 -04:00
all . Use ( ) ;
2021-11-26 11:59:02 -05:00
if ( m_renderer ) { // Choix d'algorithme de rendu pour comparer.
Vector3f direct = m_player . GetDirection ( ) ;
Vector3f renderpos = m_player . GetPosition ( ) ;
2021-11-19 11:11:08 -05:00
2021-11-26 11:59:02 -05:00
direct . y = 0 ;
direct . Normalize ( ) ;
Vector3f viewL = renderpos - direct * CHUNK_SIZE_X * 2 ,
viewR = viewL ;
viewL . Dot ( direct ) ;
viewR . Dot ( direct ) ;
for ( int x = - 3 ; x < = VIEW_DISTANCE / CHUNK_SIZE_X ; + + x ) {
int chunkxL = - 1 , chunkyL = - 1 , chunkxR = - 1 , chunkyR = - 1 ;
if ( m_world . ChunkAt ( viewL ) ) {
chunkxL = m_world . ChunkAt ( viewL ) - > GetPosX ( ) ;
chunkyL = m_world . ChunkAt ( viewL ) - > GetPosY ( ) ;
}
if ( m_world . ChunkAt ( viewR ) ) {
chunkxR = m_world . ChunkAt ( viewR ) - > GetPosX ( ) ;
chunkyR = m_world . ChunkAt ( viewR ) - > GetPosY ( ) ;
2021-11-19 11:11:08 -05:00
}
2021-11-26 11:59:02 -05:00
if ( chunkxL = = chunkxR ) {
+ + chunkxR ;
- - chunkxL ;
}
if ( chunkyL = = chunkyR ) {
+ + chunkyR ;
- - chunkyL ;
2021-11-19 11:11:08 -05:00
}
2021-11-15 20:58:13 -05:00
2021-11-26 11:59:02 -05:00
if ( chunkxL > = 0 & & chunkyL > = 0 & & chunkxR > = 0 & & chunkyR > = 0 )
for ( int rx = chunkxL ; rx ! = chunkxR ; chunkxL < chunkxR ? + + rx : - - rx )
for ( int ry = chunkyL ; ry ! = chunkyR ; chunkyL < chunkyR ? + + ry : - - ry )
if ( m_world . GetChunks ( ) . Get ( rx , ry ) ) {
m_world . GetChunks ( ) . Get ( rx , ry ) - > Render ( ) ;
+ + m_renderCount ;
}
viewL . x + = ( direct . x + direct . z ) * CHUNK_SIZE_X / 2 ;
viewL . z + = ( direct . z - direct . x ) * CHUNK_SIZE_X / 2 ;
viewR . x + = ( direct . x - direct . z ) * CHUNK_SIZE_X / 2 ;
viewR . z + = ( direct . z + direct . x ) * CHUNK_SIZE_X / 2 ;
}
}
else {
for ( int chx = 0 ; chx < WORLD_SIZE_X ; chx + + )
for ( int chy = 0 ; chy < WORLD_SIZE_Y ; chy + + )
if ( m_world . GetChunks ( ) . Get ( chx , chy ) ) {
m_world . GetChunks ( ) . Get ( chx , chy ) - > Render ( ) ;
+ + m_renderCount ;
}
}
2021-10-25 10:50:08 -04:00
m_shader01 . Disable ( ) ;
2021-09-27 10:20:58 -04:00
2021-11-26 11:59:02 -05:00
if ( m_mouseL )
GetBlockAtCursor ( BTYPE_DIRT ) ;
else if ( m_mouseR ) GetBlockAtCursor ( BTYPE_AIR ) ;
2021-10-26 17:28:37 -04:00
if ( m_wireframe )
glPolygonMode ( GL_FRONT_AND_BACK , GL_FILL ) ;
DrawHud ( elapsedTime ) ;
if ( m_wireframe )
glPolygonMode ( GL_FRONT_AND_BACK , GL_LINE ) ;
2021-11-26 11:59:02 -05:00
if ( m_player . GetPosition ( ) . y < - 20.f )
m_player = Player ( Vector3f ( CHUNK_SIZE_X * WORLD_SIZE_X / 2 , CHUNK_SIZE_Y , CHUNK_SIZE_Z * WORLD_SIZE_X / 2 ) ) ; // Respawn si le bonho- joueur tombe en bas du monde.
2021-09-24 10:15:43 -04:00
}
void Engine : : KeyPressEvent ( unsigned char key )
{
2021-10-11 11:37:58 -04:00
switch ( key ) {
2021-09-27 10:20:58 -04:00
case 36 : // ESC
Stop ( ) ;
break ;
case 94 : // F10
SetFullscreen ( ! IsFullscreen ( ) ) ;
break ;
case 22 : // W
if ( ! m_keyW ) {
std : : cout < < " W " < < std : : endl ;
m_keyW = true ;
}
break ;
case 0 : // A
if ( ! m_keyA ) {
std : : cout < < " A " < < std : : endl ;
m_keyA = true ;
}
break ;
case 18 : // S
if ( ! m_keyS ) {
std : : cout < < " S " < < std : : endl ;
m_keyS = true ;
}
break ;
case 3 : // D
if ( ! m_keyD ) {
std : : cout < < " D " < < std : : endl ;
m_keyD = true ;
}
break ;
2021-10-04 12:29:10 -04:00
case 38 : // Left Shift
if ( ! m_keylshift ) {
std : : cout < < " Dash! " < < std : : endl ;
m_keylshift = true ;
}
break ;
2021-10-01 10:52:33 -04:00
case 57 : // Space
if ( ! m_keySpace ) {
std : : cout < < " Jump! " < < std : : endl ;
m_keySpace = true ;
}
break ;
2021-09-27 10:20:58 -04:00
case 24 : // Y - Ignorer
case 255 : // Fn - Ignorer
2021-10-19 10:27:59 -04:00
case 12 : // M - Ignorer
2021-11-26 11:59:02 -05:00
case 17 : // R - Ignorer
2021-09-27 10:20:58 -04:00
break ;
default :
std : : cout < < " Unhandled key: " < < ( int ) key < < std : : endl ;
}
2021-09-24 10:15:43 -04:00
}
void Engine : : KeyReleaseEvent ( unsigned char key )
{
2021-10-11 11:37:58 -04:00
switch ( key ) {
2021-10-19 10:27:59 -04:00
case 12 :
2021-10-25 10:50:08 -04:00
m_audio . ToggleMusicState ( ) ;
2021-10-19 10:27:59 -04:00
break ;
2021-11-26 11:59:02 -05:00
case 17 :
m_renderer = ! m_renderer ;
break ;
2021-09-27 10:20:58 -04:00
case 24 : // Y
m_wireframe = ! m_wireframe ;
if ( m_wireframe )
glPolygonMode ( GL_FRONT_AND_BACK , GL_LINE ) ;
else
glPolygonMode ( GL_FRONT_AND_BACK , GL_FILL ) ;
break ;
case 22 : // W
std : : cout < < " rW " < < std : : endl ;
m_keyW = false ;
break ;
case 0 : // A
std : : cout < < " rA " < < std : : endl ;
m_keyA = false ;
break ;
case 18 : // S
std : : cout < < " rS " < < std : : endl ;
m_keyS = false ;
break ;
case 3 : // D
std : : cout < < " rD " < < std : : endl ;
m_keyD = false ;
break ;
2021-10-04 12:29:10 -04:00
case 38 : // Left Shift
std : : cout < < " rLS " < < std : : endl ;
m_keylshift = false ;
case 57 : // Espace
2021-10-01 10:52:33 -04:00
std : : cout < < " rSpace " < < std : : endl ;
m_keySpace = false ;
break ;
2021-09-27 10:20:58 -04:00
}
2021-09-24 10:15:43 -04:00
}
void Engine : : MouseMoveEvent ( int x , int y )
{
2021-10-04 12:29:10 -04:00
m_player . TurnLeftRight ( x - ( Width ( ) / 2 ) ) ;
m_player . TurnTopBottom ( y - ( Height ( ) / 2 ) ) ;
2021-09-27 13:15:57 -04:00
2021-09-27 10:20:58 -04:00
// Centrer la souris seulement si elle n'est pas d<> j<EFBFBD> centr<74> e
// Il est n<> cessaire de faire la v<> rification pour <20> viter de tomber
// dans une boucle infinie o<> l'appel <20> CenterMouse g<> n<EFBFBD> re un
// MouseMoveEvent, qui rapelle CenterMouse qui rapelle un autre
// MouseMoveEvent, etc
if ( x = = ( Width ( ) / 2 ) & & y = = ( Height ( ) / 2 ) )
return ;
CenterMouse ( ) ;
2021-09-24 10:15:43 -04:00
}
2021-11-26 11:59:02 -05:00
void Engine : : MousePressEvent ( const MOUSE_BUTTON & button , int x , int y ) {
switch ( button ) {
case MOUSE_BUTTON_LEFT :
m_mouseL = true ;
break ;
case MOUSE_BUTTON_RIGHT :
m_mouseR = true ;
break ;
case MOUSE_BUTTON_MIDDLE :
m_mouseC = true ;
break ;
case MOUSE_BUTTON_WHEEL_UP :
m_mouseWU = true ;
break ;
case MOUSE_BUTTON_WHEEL_DOWN :
m_mouseWD = true ;
break ;
case MOUSE_BUTTON_NONE : break ;
}
2021-09-24 10:15:43 -04:00
}
2021-11-26 11:59:02 -05:00
void Engine : : MouseReleaseEvent ( const MOUSE_BUTTON & button , int x , int y ) {
switch ( button ) {
case MOUSE_BUTTON_LEFT :
m_mouseL = false ;
break ;
case MOUSE_BUTTON_RIGHT :
m_mouseR = false ;
break ;
case MOUSE_BUTTON_MIDDLE :
m_mouseC = false ;
break ;
case MOUSE_BUTTON_WHEEL_UP :
m_mouseWU = false ;
break ;
case MOUSE_BUTTON_WHEEL_DOWN :
m_mouseWD = false ;
break ;
case MOUSE_BUTTON_NONE : break ;
}
2021-09-24 10:15:43 -04:00
}
bool Engine : : LoadTexture ( Texture & texture , const std : : string & filename , bool stopOnError )
{
2021-09-27 10:20:58 -04:00
texture . Load ( filename ) ;
if ( ! texture . IsValid ( ) )
{
std : : cerr < < " Unable to load texture ( " < < filename < < " ) " < < std : : endl ;
if ( stopOnError )
Stop ( ) ;
2021-09-24 10:15:43 -04:00
2021-09-27 10:20:58 -04:00
return false ;
}
2021-09-24 10:15:43 -04:00
2021-09-27 10:20:58 -04:00
return true ;
2021-09-24 10:15:43 -04:00
}
2021-11-26 11:59:02 -05:00
bool Engine : : GenerateChunk ( int chx , int chy ) {
if ( chx < WORLD_SIZE_X * CHUNK_SIZE_X & & chy < WORLD_SIZE_Y * CHUNK_SIZE_Z & &
chx > = 0 & & chy > = 0 )
if ( ! m_world . ChunkAt ( chx , 1 , chy ) ) {
m_world . GetChunks ( ) . Set ( chx / CHUNK_SIZE_X , chy / CHUNK_SIZE_Z , new Chunk ( chx / CHUNK_SIZE_X , chy / CHUNK_SIZE_Z ) ) ;
Chunk * chunk = m_world . GetChunks ( ) . Get ( chx / CHUNK_SIZE_X , chy / CHUNK_SIZE_Z ) ;
for ( int x = 0 ; x < CHUNK_SIZE_X ; + + x )
for ( int z = 0 ; z < CHUNK_SIZE_Z ; + + z )
for ( int y = 0 ; y < 32 ; + + y )
chunk - > SetBlock ( x , y , z , ( chx + chy ) % ( BTYPE_LAST - 1 ) + 1 , & m_world ) ;
chunk - > SetBlock ( 5 , 32 , 15 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 5 , 33 , 15 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 5 , 34 , 15 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 6 , 34 , 15 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 7 , 34 , 15 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 7 , 33 , 15 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 7 , 32 , 15 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 8 , 32 , 3 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 8 , 33 , 4 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 8 , 34 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 8 , 35 , 6 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 11 , 32 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 11 , 33 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 11 , 34 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 11 , 35 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 12 , 32 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 12 , 33 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 12 , 34 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 12 , 35 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 13 , 32 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 13 , 33 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 13 , 34 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 13 , 35 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 14 , 32 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 14 , 33 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 14 , 34 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 14 , 35 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 32 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 33 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 34 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 35 , 5 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 32 , 6 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 33 , 6 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 34 , 6 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 35 , 6 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 32 , 7 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 33 , 7 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 34 , 7 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 35 , 7 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 32 , 8 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 33 , 8 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 34 , 8 , BTYPE_GRASS , & m_world ) ;
chunk - > SetBlock ( 3 , 35 , 8 , BTYPE_GRASS , & m_world ) ;
std : : cout < < " Chunk generated: " < < chx / CHUNK_SIZE_X < < " , " < < chy / CHUNK_SIZE_Z < < std : : endl ;
return true ;
}
return false ;
}
void Engine : : UpdateWorld ( int & generates , int & updates , int chx , int chy ) {
if ( generates = = 0 & & GenerateChunk ( chx , chy ) ) generates = FRAMES_RENDER_CHUNKS ;
if ( updates = = 0 & & m_world . ChunkAt ( chx , 1 , chy ) & &
m_world . ChunkAt ( chx , 1 , chy ) - > IsDirty ( ) ) {
m_world . ChunkAt ( chx , 1 , chy ) - > Update ( m_blockinfo , & m_world ) ;
updates = FRAMES_UPDATE_CHUNKS ;
}
}
void Engine : : GetBlockAtCursor ( BlockType blockType )
{
int x = Width ( ) / 2 ;
int y = Height ( ) / 2 ;
Vector3f currentBlock ;
Vector3f currentFaceNormal ;
GLint viewport [ 4 ] ;
GLdouble modelview [ 16 ] ;
GLdouble projection [ 16 ] ;
GLfloat winX , winY , winZ ;
GLdouble posX , posY , posZ ;
glGetDoublev ( GL_MODELVIEW_MATRIX , modelview ) ;
glGetDoublev ( GL_PROJECTION_MATRIX , projection ) ;
glGetIntegerv ( GL_VIEWPORT , viewport ) ;
winX = ( float ) x ;
winY = ( float ) viewport [ 3 ] - ( float ) y ;
glReadPixels ( x , int ( winY ) , 1 , 1 , GL_DEPTH_COMPONENT , GL_FLOAT , & winZ ) ;
gluUnProject ( winX , winY , winZ , modelview , projection , viewport , & posX , & posY , & posZ ) ;
// Le cast vers int marche juste pour les valeurs entiere, utiliser une fonction de la libc si besoin
// de valeurs negatives
int px = ( int ) ( posX ) ;
int py = ( int ) ( posY ) ;
int pz = ( int ) ( posZ ) ;
bool found = false ;
if ( ( m_player . GetPosition ( ) - Vector3f ( ( float ) posX , ( float ) posY , ( float ) posZ ) ) . Length ( ) < MAX_SELECTION_DISTANCE )
{
// Apres avoir determine la position du bloc en utilisant la partie entiere du hit
// point retourne par opengl, on doit verifier de chaque cote du bloc trouve pour trouver
// le vrai bloc. Le vrai bloc peut etre different a cause d'erreurs de precision de nos
// nombres flottants (si z = 14.999 par exemple, et qu'il n'y a pas de blocs a la position
// 14 (apres arrondi vers l'entier) on doit trouver et retourner le bloc en position 15 s'il existe
// A cause des erreurs de precisions, ils arrive que le cote d'un bloc qui doit pourtant etre a la
// position 15 par exemple nous retourne plutot la position 15.0001
for ( int x = px - 1 ; ! found & & x < = px + 1 ; + + x ) {
for ( int y = py - 1 ; ! found & & x > = 0 & & y < = py + 1 ; + + y ) {
for ( int z = pz - 1 ; ! found & & y > = 0 & & z < = pz + 1 ; + + z ) {
if ( z > = 0 ) {
BlockType bt = m_world . BlockAt ( ( float ) x , ( float ) y , ( float ) z ) ;
if ( bt = = BTYPE_AIR )
continue ;
// Skip water blocs
//if(bloc->Type == BT_WATER)
// continue;
currentBlock . x = x ;
currentBlock . y = y ;
currentBlock . z = z ;
if ( InRangeWithEpsilon < float > ( ( float ) posX , ( float ) x , ( float ) x + 1.f , 0.05f ) & & InRangeWithEpsilon < float > ( ( float ) posY , ( float ) y , ( float ) y + 1.f , 0.05f ) & & InRangeWithEpsilon < float > ( ( float ) posZ , ( float ) z , ( float ) z + 1.f , 0.05f ) )
{
found = true ;
}
}
}
}
}
}
if ( ! found ) {
currentBlock . x = - 1 ;
}
else {
// Find on which face of the bloc we got an hit
currentFaceNormal . Zero ( ) ;
const float epsilon = 0.01f ;
// Front et back:
if ( blockType ! = BTYPE_AIR )
if ( EqualWithEpsilon < float > ( ( float ) posZ , ( float ) currentBlock . z , epsilon ) )
currentFaceNormal . z = - 1 ;
else if ( EqualWithEpsilon < float > ( ( float ) posZ , ( float ) currentBlock . z + 1.f , epsilon ) )
currentFaceNormal . z = 1 ;
else if ( EqualWithEpsilon < float > ( ( float ) posX , ( float ) currentBlock . x , epsilon ) )
currentFaceNormal . x = - 1 ;
else if ( EqualWithEpsilon < float > ( ( float ) posX , ( float ) currentBlock . x + 1.f , epsilon ) )
currentFaceNormal . x = 1 ;
else if ( EqualWithEpsilon < float > ( ( float ) posY , ( float ) currentBlock . y , epsilon ) )
currentFaceNormal . y = - 1 ;
else if ( EqualWithEpsilon < float > ( ( float ) posY , ( float ) currentBlock . y + 1.f , epsilon ) )
currentFaceNormal . y = 1 ;
currentBlock + = currentFaceNormal ;
int bx = ( int ) currentBlock . x % CHUNK_SIZE_X ;
int by = ( int ) currentBlock . y % CHUNK_SIZE_Y ;
int bz = ( int ) currentBlock . z % CHUNK_SIZE_Z ;
m_world . ChunkAt ( currentBlock ) - > SetBlock ( bx , by , bz , blockType , & m_world ) ;
m_world . ChunkAt ( currentBlock ) - > MakeModified ( ) ;
}
}