#include #include #include #include #include #include #include #include #include #include #include #include #include const nv::uint16 size_x = 16; const nv::uint16 size_y = 16; const nv::uint16 size_xy = size_x * size_y; static 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, }; static 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, }; class application { public: application(); bool initialize(); 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::image_data* sprites = m_device->create_image_data( "spritesheet.png" ); nv::sampler sampler( nv::sampler::NEAREST, nv::sampler::REPEAT ); m_texture = m_device->create_texture2d( sprites->get_size(), nv::RGBA, nv::UBYTE, sampler, (void*)sprites->get_data() ); delete sprites; 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 nv::mesh cmesh; nv::vertex_attribute::list& vtx = cmesh.add_attribute("coords")->get(); nv::vertex_attribute::list& mat = cmesh.add_attribute("material")->get(); int m = 16; int x = 0; int y = 0; int h = 0; vtx.emplace_back( x, h, y ); vtx.emplace_back( x, h, y+1 ); vtx.emplace_back( x+1, h, y+1 ); vtx.emplace_back( x+1, h, y+1 ); vtx.emplace_back( x+1, h, y ); vtx.emplace_back( x, h, y ); mat.insert( mat.end(), 6, nv::i8vec3( m, 1, 0 ) ); m_char_program = m_device->create_program( nv::slurp( "char.vert" ), nv::slurp( "char.frag" ) ); m_char_va = m_device->create_vertex_array( &cmesh, &(m_char_program->get_attributes()), nv::STATIC_DRAW ); } { // WORLD nv::mesh wmesh; nv::vertex_attribute::list& vtx = wmesh.add_attribute("coords")->get(); nv::vertex_attribute::list& mat = wmesh.add_attribute("material")->get(); for (int i = 0; i < size_x * size_y; ++i ) { int x = i % size_x; int y = i / size_x; vtx.emplace_back( x, height[i], y ); vtx.emplace_back( x, height[i], y+1 ); vtx.emplace_back( x+1, height[i], y+1 ); vtx.emplace_back( x+1, height[i], y+1 ); vtx.emplace_back( x+1, height[i], y ); vtx.emplace_back( x, height[i], y ); mat.insert( mat.end(), 6, nv::i8vec3( 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 ) { m_count += 6; vtx.emplace_back( x, h, y ); vtx.emplace_back( x, h, y+1 ); vtx.emplace_back( x, h+dir, y+1 ); vtx.emplace_back( x, h+dir, y+1 ); vtx.emplace_back( x, h+dir, y ); vtx.emplace_back( x, h, y ); mat.insert( mat.end(), 6, nv::i8vec3( 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 ) { vtx.emplace_back( x, h, y ); vtx.emplace_back( x, h+dir, y ); vtx.emplace_back( x+1, h+dir, y ); vtx.emplace_back( x+1, h+dir, y ); vtx.emplace_back( x+1, h, y ); vtx.emplace_back( x, h, y ); mat.insert( mat.end(), 6, nv::i8vec3( m, -3*dir, 0 ) ); } } } m_count = vtx.size(); m_box_program = m_device->create_program( nv::slurp( "box.vert" ), nv::slurp( "box.frag" ) ); m_box_va = m_device->create_vertex_array( &wmesh, &(m_box_program->get_attributes()), nv::STATIC_DRAW ); } 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 ); m_window->swap_buffers(); nv::io_event event; while(m_window->poll_event(event)) { switch (event.type) { case nv::EV_QUIT: keypress = 1; break; case nv::EV_KEY: if (event.key.pressed) { switch (event.key.code) { case nv::KEY_ESCAPE : keypress = 1; break; case nv::KEY_LEFT : move.x = move.x - 1.0f; break; case nv::KEY_RIGHT : move.x = move.x + 1.0f; break; case nv::KEY_UP : move.z = move.z - 1.0f; break; case nv::KEY_DOWN : move.z = move.z + 1.0f; break; default: break; } } break; default: 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; }