#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef glm::detail::tvec3 byte3; const nv::uint16 size_x = 16; const nv::uint16 size_y = 16; const nv::uint16 size_xy = size_x * size_y; nv::uint8 height[size_xy] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 5, 5, 5, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 4, 4, 4, 4, 4, 4, }; nv::uint8 map[size_xy] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 6, 6, 2, 2, 2, 2, 2, 2, }; struct world; struct being; class application { public: application(); bool initialize(); bool init_program( const std::string& name, nv::program*& p, nv::vertex_array*& va, int count, void* vertex, void* material ); bool run(); ~application(); protected: nv::device* m_device; nv::window* m_window; nv::texture2d* m_texture; nv::clear_state m_clear_state; nv::render_state m_render_state; nv::program* m_char_program; nv::program* m_box_program; nv::vertex_array* m_char_va; nv::vertex_array* m_box_va; unsigned int m_count; }; application::application() { m_device = new nv::gl_device(); m_window = m_device->create_window( 800, 600 ); nv::load_sdl_image_library(); SDL_Surface* texture = IMG_Load( "spritesheet.png" ); nv::image sprites( glm::ivec2( texture->w, texture->h ), 4, (nv::uint8*)texture->pixels ); nv::texture2d_sampler sampler( nv::texture2d_sampler::NEAREST, nv::texture2d_sampler::REPEAT ); m_texture = m_device->create_texture2d( sprites.get_size(), nv::texture2d::RGBA, nv::texture2d::UBYTE, sampler, (void*)sprites.get_data() ); m_clear_state.buffers = nv::clear_state::COLOR_AND_DEPTH_BUFFER; m_render_state.depth_test.enabled = true; m_render_state.blending.enabled = true; m_render_state.blending.src_rgb_factor = nv::blending::SRC_ALPHA; m_render_state.blending.dst_rgb_factor = nv::blending::ONE_MINUS_SRC_ALPHA; m_render_state.blending.src_alpha_factor = nv::blending::SRC_ALPHA; m_render_state.blending.dst_alpha_factor = nv::blending::ONE_MINUS_SRC_ALPHA; } bool application::initialize() { { // CHARACTER byte3 vertex[6]; byte3 material[6]; int m = 16; int x = 0; int y = 0; int h = 0; vertex[0] = byte3( x, h, y ); material[0] = byte3( m, 1, 0 ); vertex[1] = byte3( x, h, y+1 ); material[1] = byte3( m, 1, 0 ); vertex[2] = byte3( x+1, h, y+1 ); material[2] = byte3( m, 1, 0 ); vertex[3] = byte3( x+1, h, y+1 ); material[3] = byte3( m, 1, 0 ); vertex[4] = byte3( x+1, h, y ); material[4] = byte3( m, 1, 0 ); vertex[5] = byte3( x, h, y ); material[5] = byte3( m, 1, 0 ); if (!init_program( "char", m_char_program, m_char_va, 6, vertex, material ) ) return false; } { // WORLD byte3 vertex[size_x * size_y * 256]; byte3 material[size_x * size_y * 256]; m_count = 0; int mcount = 0; for (int i = 0; i < size_x * size_y; ++i ) { int x = i % size_x; int y = i / size_x; vertex[m_count++] = byte3( x, height[i], y ); material[mcount++] = byte3( map[i], 2, 0 ); vertex[m_count++] = byte3( x, height[i], y+1 ); material[mcount++] = byte3( map[i], 2, 0 ); vertex[m_count++] = byte3( x+1, height[i], y+1 ); material[mcount++] = byte3( map[i], 2, 0 ); vertex[m_count++] = byte3( x+1, height[i], y+1 ); material[mcount++] = byte3( map[i], 2, 0 ); vertex[m_count++] = byte3( x+1, height[i], y ); material[mcount++] = byte3( map[i], 2, 0 ); vertex[m_count++] = byte3( x, height[i], y ); material[mcount++] = byte3( map[i], 2, 0 ); if (i > 0 && height[i-1] != height[i]) { short dir = height[i-1] > height[i] ? -1 : 1; nv::uint8 m = 1; for ( int h = height[i-1]; h != height[i]; h = h + dir ) { vertex[m_count++] = byte3( x, h, y ); material[mcount++] = byte3( m, -dir, 0 ); vertex[m_count++] = byte3( x, h, y+1 ); material[mcount++] = byte3( m, -dir, 0 ); vertex[m_count++] = byte3( x, h+dir, y+1 ); material[mcount++] = byte3( m, -dir, 0 ); vertex[m_count++] = byte3( x, h+dir, y+1 ); material[mcount++] = byte3( m, -dir, 0 ); vertex[m_count++] = byte3( x, h+dir, y ); material[mcount++] = byte3( m, -dir, 0 ); vertex[m_count++] = byte3( x, h, y ); material[mcount++] = byte3( m, -dir, 0 ); } } if (i >= size_x && height[i-size_x] != height[i]) { short dir = height[i-size_x] > height[i] ? -1 : 1; nv::uint8 m = 1; for ( int h = height[i-size_x]; h != height[i]; h = h + dir ) { vertex[m_count++] = byte3( x, h, y ); material[mcount++] = byte3( m, -3*dir, 0 ); vertex[m_count++] = byte3( x, h+dir, y ); material[mcount++] = byte3( m, -3*dir, 0 ); vertex[m_count++] = byte3( x+1, h+dir, y ); material[mcount++] = byte3( m, -3*dir, 0 ); vertex[m_count++] = byte3( x+1, h+dir, y ); material[mcount++] = byte3( m, -3*dir, 0 ); vertex[m_count++] = byte3( x+1, h, y ); material[mcount++] = byte3( m, -3*dir, 0 ); vertex[m_count++] = byte3( x, h, y ); material[mcount++] = byte3( m, -3*dir, 0 ); } } } if (!init_program( "box", m_box_program, m_box_va, m_count, vertex, material ) ) return false; } return true; } bool application::init_program( const std::string& name, nv::program*& p, nv::vertex_array*& va, int count, void* vertex, void* material ) { p = m_device->create_program( nv::slurp( name+".vert" ), nv::slurp( name+".frag" ) ); va = m_device->create_vertex_array(); nv::attribute* a; a = p->get_attribute( "coords" ); if (a == nullptr) return false; nv::vertex_buffer* vbcoords = m_device->create_vertex_buffer( nv::STATIC_DRAW, count*sizeof(byte3), vertex ); va->add_vertex_buffer( a->get_location(), vbcoords, nv::BYTE, 3 ); a = p->get_attribute( "material" ); if (a == nullptr) return false; nv::vertex_buffer* vbmaterial = m_device->create_vertex_buffer( nv::STATIC_DRAW, count*sizeof(byte3), material ); va->add_vertex_buffer( a->get_location(), vbmaterial, nv::BYTE, 3 ); return true; } bool application::run() { int keypress = 0; glm::vec3 move( 0, 0, 0 ); while(!keypress) { m_window->get_context()->clear( m_clear_state ); glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(-8.5, 0.0, -8.0)); glm::mat4 view = glm::lookAt(glm::vec3(0.0, 20.0, 5.0) + move, glm::vec3(0.0, 4.0, 0.0) + move, glm::vec3(0.0, 1.0, 0.0)); glm::mat4 projection = glm::perspective(25.0f, 1.0f*800.0f/600.0f, 0.1f, 100.0f); glm::mat4 mv = view * model; m_texture->bind( 0 ); m_box_program->set_uniform( "matrix_mvp", projection * mv ); m_box_program->set_uniform( "light", glm::vec3(8.5, 4.5, 6.5) + move ); m_box_program->set_uniform( "tex", 0 ); m_window->get_context()->draw( nv::TRIANGLES, m_render_state, m_box_program, m_box_va, m_count ); m_char_program->set_uniform( "matrix_mvp", projection * mv ); m_char_program->set_uniform( "pos", move + glm::vec3( 8, 4.1, 6 ) ); m_char_program->set_uniform( "tex", 0 ); m_window->get_context()->draw( nv::TRIANGLES, m_render_state, m_char_program, m_char_va, 6 ); SDL_GL_SwapBuffers(); SDL_Event event; while(SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: keypress = 1; break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_ESCAPE: keypress = 1; break; case SDLK_LEFT: move.x = move.x - 1.0f; break; case SDLK_RIGHT: move.x = move.x + 1.0f; break; case SDLK_UP: move.z = move.z - 1.0f; break; case SDLK_DOWN: move.z = move.z + 1.0f; break; } break; } } } return true; } application::~application() { delete m_char_program; delete m_box_program; delete m_char_va; delete m_box_va; delete m_texture; delete m_window; delete m_device; } int main(int, char* []) { nv::logger log(nv::LOG_TRACE); log.add_sink( new nv::log_file_sink("log.txt"), nv::LOG_TRACE ); log.add_sink( new nv::log_console_sink(), nv::LOG_TRACE ); NV_LOG( nv::LOG_NOTICE, "Logging started" ); application app; if ( app.initialize() ) { app.run(); } NV_LOG( nv::LOG_NOTICE, "Logging stopped" ); return 0; }