medfall

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 4c98757ce2194a224149e1dcc42729a7c4ab7a51
parent 2b429b044904e0bb56330ed041cb367decbb6c7d
Author: Michael Savage <mikejsavage@gmail.com>
Date:   Sat Aug  1 23:28:39 +0200

Initial work on terrain paging

Diffstat:
Makefile | 2+-
README.md | 1+
heightmap.cc | 73+++++++++++++++++++++++++++++++++++++++++++++----------------------------
heightmap.h | 16+++++++++-------
hm.cc | 14++++++++++----
terrain_manager.cc | 168+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
terrain_manager.h | 41+++++++++++++++++++++++++++++++++++++++++
tiles.png | 0
8 files changed, 275 insertions(+), 40 deletions(-)
diff --git a/Makefile b/Makefile @@ -3,7 +3,7 @@ all: bsp hm pp BSPSRCS = bsp.cc bsp_renderer.cc gl.cc BSPOBJS := $(patsubst %.cc,%.o,$(BSPSRCS)) -HMSRCS = hm.cc gl.cc heightmap.cc stb_image.cc stb_perlin.cc +HMSRCS = hm.cc gl.cc heightmap.cc terrain_manager.cc stb_image.cc stb_perlin.cc HMOBJS := $(patsubst %.cc,%.o,$(HMSRCS)) PPSRCS = pp.cc stb_image.cc stb_image_write.cc diff --git a/README.md b/README.md @@ -1,2 +1,3 @@ ![BSP renderer](bsp.png) ![Terrain renderer](hm.png) +![Terrain paging](tiles.png) diff --git a/heightmap.cc b/heightmap.cc @@ -160,11 +160,29 @@ glm::vec3 triangle_perp_ccw( const glm::vec3 & a, const glm::vec3 & b, const glm return glm::cross( b - a, c - a ); } -void Heightmap::init( const std::string image ) { +Heightmap::~Heightmap() { + unload(); + glDeleteProgram( shader ); +} + +void Heightmap::init() { + shader = compile_shader( vert_src, frag_src, "colour" ); + + at_pos = glGetAttribLocation( shader, "position" ); + at_normal = glGetAttribLocation( shader, "normal" ); + at_lit = glGetAttribLocation( shader, "lit" ); + + un_vp = glGetUniformLocation( shader, "vp" ); + un_sun = glGetUniformLocation( shader, "sun" ); +} + +void Heightmap::load( const std::string & image, const int ox, const int oy ) { + printf( "%s offset by %dx%d\n", image.c_str(), ox, oy ); pixels = stbi_load( image.c_str(), &w, &h, nullptr, 1 ); - printf( "begin lit calculations\n" ); - lit = new GLfloat[ w * h ]; + // printf( "begin lit calculations\n" ); + + float * const lit = new GLfloat[ w * h ]; for( int i = 0; i < w * h; i++ ) { lit[ i ] = 0; } @@ -201,28 +219,22 @@ void Heightmap::init( const std::string image ) { } } - printf( "end lit calculations\n" ); + // printf( "end lit calculations\n" ); + // + // printf( "sending data to gpu\n" ); - printf( "sending data to gpu\n" ); - shader = compile_shader( vert_src, frag_src, "colour" ); - at_pos = glGetAttribLocation( shader, "position" ); - at_normal = glGetAttribLocation( shader, "normal" ); - at_lit = glGetAttribLocation( shader, "lit" ); - un_vp = glGetUniformLocation( shader, "vp" ); - un_sun = glGetUniformLocation( shader, "sun" ); - - GLfloat * vertices = new GLfloat[ w * h * 3 ]; - GLfloat * normals = new GLfloat[ w * h * 3 ]; - GLuint * indices = new GLuint[ w * h * 6 ]; + GLfloat * const vertices = new GLfloat[ w * h * 3 ]; + GLfloat * const normals = new GLfloat[ w * h * 3 ]; + GLuint * const indices = new GLuint[ w * h * 6 ]; for( int y = 0; y < h; y++ ) { for( int x = 0; x < w; x++ ) { const int base = 3 * ( y * w + x ); const float height = point( x, y ).z; - vertices[ base ] = x; - vertices[ base + 1 ] = y; + vertices[ base ] = x + ox; + vertices[ base + 1 ] = y + oy; vertices[ base + 2 ] = height; const glm::vec3 normal = point_normal( x, y ); @@ -249,8 +261,8 @@ void Heightmap::init( const std::string image ) { glGenVertexArrays( 1, &vao ); glBindVertexArray( vao ); - glGenBuffers( 1, &vbo ); - glBindBuffer( GL_ARRAY_BUFFER, vbo ); + glGenBuffers( 1, &vbo_verts ); + glBindBuffer( GL_ARRAY_BUFFER, vbo_verts ); glBufferData( GL_ARRAY_BUFFER, w * h * sizeof( GLfloat ) * 3, vertices, GL_STATIC_DRAW ); glGenBuffers( 1, &vbo_normals ); @@ -263,25 +275,26 @@ void Heightmap::init( const std::string image ) { glGenBuffers( 1, &ebo ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ebo ); - glBufferData( GL_ELEMENT_ARRAY_BUFFER, ( w - 1 ) * ( h - 1 ) * sizeof( GLuint ) * 6, indices, GL_STATIC_DRAW ); + glBufferData( GL_ELEMENT_ARRAY_BUFFER, w * h * sizeof( GLuint ) * 6, indices, GL_STATIC_DRAW ); delete vertices; delete normals; delete indices; + delete lit; + stbi_image_free( pixels ); - printf( "sent\n" ); + // printf( "sent\n" ); } -Heightmap::~Heightmap() { - if( vbo != 0 ) { - glDeleteBuffers( 1, &ebo ); - glDeleteBuffers( 1, &vbo ); +void Heightmap::unload() { + if( vbo_verts != 0 ) { + glDeleteBuffers( 1, &vbo_verts ); glDeleteBuffers( 1, &vbo_normals ); glDeleteBuffers( 1, &vbo_lit ); + glDeleteBuffers( 1, &ebo ); glDeleteVertexArrays( 1, &vao ); - delete lit; - stbi_image_free( pixels ); + vbo_verts = 0; } } @@ -370,6 +383,10 @@ float Heightmap::height( const float x, const float y ) const { } void Heightmap::render( const glm::mat4 & VP ) const { + if( vbo_verts == 0 ) { + return; + } + const glm::vec3 sun = glm::normalize( glm::vec3( 1, 0, -SLOPE ) ); glUseProgram( shader ); @@ -378,7 +395,7 @@ void Heightmap::render( const glm::mat4 & VP ) const { glUniformMatrix4fv( un_vp, 1, GL_FALSE, glm::value_ptr( VP ) ); glUniform3fv( un_sun, 1, glm::value_ptr( sun ) ); - glBindBuffer( GL_ARRAY_BUFFER, vbo ); + glBindBuffer( GL_ARRAY_BUFFER, vbo_verts ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ebo ); glEnableVertexAttribArray( at_pos ); glVertexAttribPointer( at_pos, 3, GL_FLOAT, GL_FALSE, 0, 0 ); diff --git a/heightmap.h b/heightmap.h @@ -13,28 +13,30 @@ private: u8 * pixels; int w, h; - float * lit; - - GLuint vbo = 0; + GLuint vbo_verts = 0; GLuint vbo_normals; GLuint vbo_lit; - GLuint vao; GLuint ebo; + GLuint vao; GLuint shader; + GLint at_pos; GLint at_normal; GLint at_lit; + GLint un_vp; GLint un_sun; public: - void init( const std::string image ); - ~Heightmap(); - glm::vec3 point( int x, int y ) const; + void init(); + void load( const std::string & image, const int ox, const int oy ); + void unload(); + + glm::vec3 point( int x, int y ) const; glm::vec3 point_normal( int x, int y ) const; float height( const float x, const float y ) const; diff --git a/hm.cc b/hm.cc @@ -11,6 +11,7 @@ #include "int.h" #include "gl.h" #include "heightmap.h" +#include "terrain_manager.h" #include "stb_easy_font.h" #include "stb_image.h" #include "stb_perlin.h" @@ -45,8 +46,9 @@ void print_vec3( const std::string & name, const glm::vec3 & v ) { int main( int argc, char ** argv ) { GLFWwindow * const window = GL::init(); - Heightmap hm; - hm.init( argc == 2 ? argv[ 1 ] : "mountains512.png" ); + const std::string map = argc == 2 ? argv[ 1 ] : "mountains512.png" ; + + TerrainManager tm( map + ".parts" ); const float start_time = glfwGetTime(); u32 frames = 0; @@ -54,9 +56,11 @@ int main( int argc, char ** argv ) { glClearColor( 0, 0.5, 0.7, 1 ); - glm::vec3 pos( 0, 0, 50 ); + glm::vec3 pos( 15000, 3000, 50 ); glm::vec3 angles = glm::radians( glm::vec3( -90, 45, 0 ) ); + tm.teleport( pos ); + const glm::mat4 P = glm::perspective( glm::radians( 120.0f ), 640.0f / 480.0f, 0.1f, 10000.0f ); while( !glfwWindowShouldClose( window ) ) { @@ -85,6 +89,8 @@ int main( int argc, char ** argv ) { // pos.z = hm.height( pos.x, pos.y ) + 8; pos.z += dz * 50.0f * dt; + tm.update( pos ); + const glm::mat4 VP = glm::translate( glm::rotate( glm::rotate( @@ -98,7 +104,7 @@ int main( int argc, char ** argv ) { -pos ); - hm.render( VP ); + tm.render( VP ); // glLoadIdentity(); // diff --git a/terrain_manager.cc b/terrain_manager.cc @@ -0,0 +1,168 @@ +/* + * I use the following naming conventions in this file:: + * TODO: no i dont + * + * - tx/ty are used to denote tile coordinates + * - ptx/pty are used to denote the player's tile coordinates + * - x/y are used to denote local coordinates within a tile + * - wx/wy are used to denote global coordinates + */ + +#include <string> + +#include <glm/glm.hpp> + +#include "int.h" +#include "heightmap.h" +#include "terrain_manager.h" + +TerrainManager::TerrainManager( const std::string & dir ) : dir( dir ) { + FILE * dims = fopen( ( dir + "/dims.txt" ).c_str(), "r" ); + fscanf( dims, "%d %d", &w, &h ); + fclose( dims ); + printf( "%d %d\n", w, h ); + + for( int ty = 0; ty < REGION_SIZE; ty++ ) { + for( int tx = 0; tx < REGION_SIZE; tx++ ) { + const int rx = tx - REGION_HALF; + const int ry = ty - REGION_HALF; + + if( rx == ry || rx == -ry ) { + lods[ tx ][ ty ] = std::max( 1, std::abs( rx ) + std::abs( ry ) - 1 ); + } + else { + lods[ tx ][ ty ] = std::max( std::abs( rx ), std::abs( ry ) ); + } + + tiles[ tx ][ ty ].init(); + } + } + + for( int ty = 0; ty < REGION_SIZE; ty++ ) { + for( int tx = 0; tx < REGION_SIZE; tx++ ) { + printf( "%d ", lods[ tx ][ ty ] ); + } + printf( "\n" ); + } +} + +std::string TerrainManager::tp( const int tx, const int ty ) const { + return dir + "/" + std::to_string( tx ) + "_" + std::to_string( ty ) + ".tga"; +} + +void TerrainManager::update( const glm::vec3 & position ) { + const int new_ptx = position.x / TILE_SIZE; + const int new_pty = position.y / TILE_SIZE; + + if( new_ptx != ptx ) { + if( new_ptx > ptx ) { + printf( "boundary +x\n" ); + for( int ty = 0; ty < REGION_SIZE; ty++ ) { + tiles[ 0 ][ ty ].unload(); + + for( int tx = 1; tx < REGION_SIZE; tx++ ) { + tiles[ tx - 1 ][ ty ] = std::move( tiles[ tx ][ ty ] ); + } + + tiles[ REGION_SIZE - 1 ][ ty ].load( + tp( ptx + REGION_HALF + 1, pty + ty - REGION_HALF ), + ( ptx + REGION_HALF + 1 ) * TILE_SIZE, + ( pty + ty - REGION_HALF ) * TILE_SIZE ); + } + + ptx++; + } + else { + printf( "boundary -x\n" ); + for( int ty = 0; ty < REGION_SIZE; ty++ ) { + tiles[ REGION_SIZE - 1 ][ ty ].unload(); + + for( int tx = REGION_SIZE - 2; tx >= 0; tx-- ) { + tiles[ tx + 1 ][ ty ] = std::move( tiles[ tx ][ ty ] ); + } + + tiles[ 0 ][ ty ].load( + tp( ptx - REGION_HALF - 1, pty + ty - REGION_HALF ), + ( ptx - REGION_HALF - 1 ) * TILE_SIZE, + ( pty + ty - REGION_HALF ) * TILE_SIZE ); + } + + ptx--; + } + } + + if( new_pty != pty ) { + if( new_pty > pty ) { + printf( "boundary +y\n" ); + for( int tx = 0; tx < REGION_SIZE; tx++ ) { + tiles[ tx ][ 0 ].unload(); + + for( int ty = 1; ty < REGION_SIZE; ty++ ) { + tiles[ tx ][ ty - 1 ] = std::move( tiles[ tx ][ ty ] ); + } + + tiles[ tx ][ REGION_SIZE - 1 ].load( + tp( ptx + tx - REGION_HALF, pty + REGION_HALF + 1 ), + ( ptx + tx - REGION_HALF ) * TILE_SIZE, + ( pty + REGION_HALF + 1 ) * TILE_SIZE ); + } + pty++; + } + else { + printf( "boundary -y\n" ); + for( int tx = 0; tx < REGION_SIZE; tx++ ) { + tiles[ tx ][ REGION_SIZE - 1 ].unload(); + + for( int ty = REGION_SIZE - 2; ty >= 0; ty-- ) { + tiles[ tx ][ ty + 1 ] = std::move( tiles[ tx ][ ty ] ); + } + + tiles[ tx ][ 0 ].load( + tp( ptx + tx - REGION_HALF, pty - REGION_HALF - 1 ), + ( ptx + tx - REGION_HALF ) * TILE_SIZE, + ( pty - REGION_HALF - 1 ) * TILE_SIZE ); + } + pty--; + } + } +} + +void TerrainManager::prepare_teleport( const glm::vec3 & position ) { +} + +bool TerrainManager::teleport_ready() { + return false; +} + +void TerrainManager::teleport( const glm::vec3 & position ) { + cx = cy = REGION_HALF; + ptx = position.x / TILE_SIZE; + pty = position.y / TILE_SIZE; + + for( int ty = 0; ty < REGION_SIZE; ty++ ) { + for( int tx = 0; tx < REGION_SIZE; tx++ ) { + const int ltx = ptx + tx - REGION_HALF; + const int lty = pty + ty - REGION_HALF; + + if( ltx >= 0 && ltx < w && lty >= 0 && lty < h ) { + tiles[ tx ][ ty ].load( + dir + "/" + std::to_string( ltx ) + "_" + std::to_string( lty ) + ".tga", + ltx * TILE_SIZE, + lty * TILE_SIZE + ); + } + else { + tiles[ tx ][ ty ].unload(); + } + } + } + +} + +void TerrainManager::render( const glm::mat4 & VP ) { + for( int ty = 0; ty < REGION_SIZE; ty++ ) { + for( int tx = 0; tx < REGION_SIZE; tx++ ) { + tiles[ tx ][ ty ].render( VP ); + } + } +} diff --git a/terrain_manager.h b/terrain_manager.h @@ -0,0 +1,41 @@ +#ifndef _TERRAIN_MANAGER_H_ +#define _TERRAIN_MANAGER_H_ + +#include <string> +#include <glm/glm.hpp> + +#include "int.h" + +class TerrainManager { +private: + const static int TILE_SIZE = 128; + const static int REGION_SIZE = 11; + const static int REGION_HALF = REGION_SIZE / 2; + + const std::string dir; + + int w, h; + + Heightmap tiles[ REGION_SIZE ][ REGION_SIZE ]; + Heightmap alt_tiles[ REGION_SIZE ][ REGION_SIZE ]; + + u8 lods[ REGION_SIZE ][ REGION_SIZE ]; + + int cx, cy; + int ptx, pty; + +public: + TerrainManager( const std::string & dir ); + + std::string tp( const int tx, const int ty ) const; + void update( const glm::vec3 & position ); + + // maybe these aren't needed + void prepare_teleport( const glm::vec3 & position ); + bool teleport_ready(); + void teleport( const glm::vec3 & position ); + + void render( const glm::mat4 & VP ); +}; + +#endif // _TERRAIN_MANAGER_H_ diff --git a/tiles.png b/tiles.png Binary files differ.