X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fapp.cpp;h=8c0793dfc123b4ab0f14bafd806aafc8c118f09e;hb=df75211841f870ca42c3b8bbc422ee43a517e766;hp=652e1c1bbcac54a3ba9157520fd3de69873e936a;hpb=3baab6cca7423d55ea08288d96570b02380b1fe9;p=blank.git diff --git a/src/app.cpp b/src/app.cpp index 652e1c1..8c0793d 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -1,5 +1,7 @@ #include "app.hpp" +#include "geometry.hpp" + #include #include @@ -18,224 +20,38 @@ Application::Application() , pitch_sensitivity(-0.0025f) , yaw_sensitivity(-0.001f) , cam() -, model({ - // vertices - { 0.0f, 0.0f, 1.0f }, // front, red - { 1.0f, 0.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, // back, cyan - { 0.0f, 1.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, // top, green - { 0.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, // bottom, magenta - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, // left, blue - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 1.0f, 0.0f, 0.0f }, // right, yellow - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 1.0f }, -}, { - // colors - { 1.0f, 0.0f, 0.0f }, // front, red - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 1.0f, 1.0f }, // back, cyan - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 1.0f }, - { 0.0f, 1.0f, 0.0f }, // top, green - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 1.0f, 0.0f, 1.0f }, // bottom, magenta - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 1.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, // left, blue - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 1.0f, 1.0f, 0.0f }, // right, yellow - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, -}, { - // normals - { 0.0f, 0.0f, 1.0f }, // front, red - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, -1.0f }, // back, cyan - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 1.0f, 0.0f }, // top, green - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, // bottom, magenta - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, // left, blue - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, // right, yellow - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, -}) -, modelCtrl() -, light_position(5.0f, 5.0f, 5.0f) -, light_color(1.0f, 1.0f, 1.0f) -, light_power(50.0f) -, m_handle(0) -, v_handle(0) -, mv_handle(0) -, mvp_handle(0) -, light_position_handle(0) -, light_color_handle(0) -, light_power_handle(0) +, hud() +, world() +, outline() +, outline_visible(false) +, outline_transform(1.0f) , running(false) , front(false) , back(false) , left(false) , right(false) , up(false) -, down(false) { +, down(false) +, place(false) +, remove(false) +, pick(false) +, remove_id(0) +, place_id(1) { GLContext::EnableVSync(); - GLContext::EnableBackfaceCulling(); - program.LoadShader( - GL_VERTEX_SHADER, - "#version 330 core\n" - "layout(location = 0) in vec3 vtx_position;\n" - "layout(location = 1) in vec3 vtx_color;\n" - "layout(location = 2) in vec3 vtx_normal;\n" - "uniform mat4 M;\n" - "uniform mat4 V;\n" - "uniform mat4 MVP;\n" - "uniform vec3 light_position;\n" - "out vec3 frag_color;\n" - "out vec3 vtx_world;\n" - "out vec3 normal;\n" - "out vec3 eye;\n" - "out vec3 light_direction;\n" - "void main() {\n" - "vec4 v = vec4(vtx_position, 1);\n" - "gl_Position = MVP * v;\n" - "vtx_world = (M * v).xyz;\n" - "vec3 vtx_camera = (V * M * v).xyz;\n" - "eye = vec3(0, 0, 0) - vtx_camera;\n" - "vec3 light_camera = (V * v).xyz;\n" - "light_direction = light_position + eye;\n" - "normal = (V * M * vec4(vtx_normal, 0)).xyz;\n" - "frag_color = vtx_color;\n" - "}\n" - ); - program.LoadShader( - GL_FRAGMENT_SHADER, - "#version 330 core\n" - "in vec3 frag_color;\n" - "in vec3 vtx_world;\n" - "in vec3 normal;\n" - "in vec3 eye;\n" - "in vec3 light_direction;\n" - "uniform mat4 MV;\n" - "uniform vec3 light_position;\n" - "uniform vec3 light_color;\n" - "uniform float light_power;\n" - "out vec3 color;\n" - "void main() {\n" - "vec3 ambient = vec3(0.1, 0.1, 0.1) * frag_color;\n" - "vec3 specular = vec3(0.3, 0.3, 0.3);\n" - "float distance = length(light_position - vtx_world);\n" - "vec3 n = normalize(normal);\n" - "vec3 l = normalize(light_direction);\n" - "float cos_theta = clamp(dot(n, l), 0, 1);\n" - "vec3 E = normalize(eye);\n" - "vec3 R = reflect(-l, n);\n" - "float cos_alpha = clamp(dot(E, R), 0, 1);\n" - "color = ambient" - " + frag_color * light_color * light_power * cos_theta / (distance * distance)" - " + specular * light_color * light_power * pow(cos_alpha, 5) / (distance * distance);\n" - "}\n" - ); - program.Link(); - if (!program.Linked()) { - program.Log(std::cerr); - throw std::runtime_error("link program"); - } GLuint VertexArrayID; glGenVertexArrays(1, &VertexArrayID); glBindVertexArray(VertexArrayID); - modelCtrl.Position(glm::vec3(0, 0, -4)); - cam.Position(glm::vec3(0, 0, 4)); + world.Generate(); - m_handle = program.UniformLocation("M"); - v_handle = program.UniformLocation("V"); - mv_handle = program.UniformLocation("MV"); - mvp_handle = program.UniformLocation("MVP"); - light_position_handle = program.UniformLocation("light_position"); - light_color_handle = program.UniformLocation("light_color"); - light_power_handle = program.UniformLocation("light_power"); + cam.Position(glm::vec3(0, 4, 4)); + hud.Viewport(960, 600); + hud.Display(*world.BlockTypes()[place_id]); glClearColor(0.0, 0.0, 0.0, 1.0); } -Application::~Application() { - -} - void Application::Run() { running = true; @@ -276,13 +92,27 @@ void Application::HandleEvents() { right = event.key.state == SDL_PRESSED; break; case SDLK_q: + case SDLK_SPACE: up = event.key.state == SDL_PRESSED; break; case SDLK_e: + case SDLK_LSHIFT: down = event.key.state == SDL_PRESSED; break; } break; + case SDL_MOUSEBUTTONDOWN: + if (event.button.button == 1) { + // left + remove = true; + } else if (event.button.button == 2) { + // middle + pick = true; + } else if (event.button.button == 3) { + // right + place = true; + } + break; case SDL_MOUSEMOTION: cam.RotateYaw(event.motion.xrel * yaw_sensitivity); cam.RotatePitch(event.motion.yrel * pitch_sensitivity); @@ -294,6 +124,7 @@ void Application::HandleEvents() { switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: cam.Viewport(event.window.data1, event.window.data2); + hud.Viewport(event.window.data1, event.window.data2); break; default: break; @@ -322,29 +153,74 @@ void Application::Update(int dt) { } else if (front && !back) { vel.z = -move_velocity; } - cam.Velocity(vel); + cam.OrientationVelocity(vel); cam.Update(dt); - modelCtrl.Update(dt); + + Ray aim = cam.Aim(); + Chunk *chunk; + int blkid; + float dist; + glm::vec3 normal; + if (world.Intersection(aim, glm::mat4(1.0f), &chunk, &blkid, &dist, &normal)) { + glm::vec3 pos = Chunk::ToCoords(blkid); + outline_visible = true; + outline.Clear(); + chunk->BlockAt(blkid).type->FillOutlineModel(outline); + outline_transform = glm::translate(chunk->Transform(), pos); + outline_transform = glm::scale(outline_transform, glm::vec3(1.0001f)); + } else { + outline_visible = false; + } + + if (pick) { + if (chunk) { + place_id = chunk->BlockAt(blkid).type->id; + hud.Display(*world.BlockTypes()[place_id]); + } + pick = false; + } + if (remove) { + if (chunk) { + chunk->BlockAt(blkid).type = world.BlockTypes()[remove_id]; + chunk->Invalidate(); + } + remove = false; + } + if (place) { + if (chunk) { + Chunk *mod_chunk = chunk; + glm::vec3 next_pos = Chunk::ToCoords(blkid) + normal; + if (!Chunk::InBounds(next_pos)) { + mod_chunk = &world.Next(*chunk, normal); + next_pos -= normal * Chunk::Extent(); + } + mod_chunk->BlockAt(next_pos).type = world.BlockTypes()[place_id]; + mod_chunk->Invalidate(); + } + place = false; + } } void Application::Render() { - glClear(GL_COLOR_BUFFER_BIT); + GLContext::Clear(); + + program.Activate(); - program.Use(); + program.SetLightDirection({ -1.0f, -3.0f, -2.0f }); + program.SetVP(cam.View(), cam.Projection()); - glm::mat4 m(modelCtrl.Transform()); - glm::mat4 mv(cam.View() * m); - glm::mat4 mvp(cam.MakeMVP(m)); - glUniformMatrix4fv(m_handle, 1, GL_FALSE, &m[0][0]); - glUniformMatrix4fv(v_handle, 1, GL_FALSE, &cam.View()[0][0]); - glUniformMatrix4fv(mv_handle, 1, GL_FALSE, &mv[0][0]); - glUniformMatrix4fv(mvp_handle, 1, GL_FALSE, &mvp[0][0]); - glUniform3f(light_position_handle, light_position.x, light_position.y, light_position.z); - glUniform3f(light_color_handle, light_color.x, light_color.y, light_color.z); - glUniform1f(light_power_handle, light_power); + for (Chunk &chunk : world.LoadedChunks()) { + program.SetM(chunk.Transform()); + chunk.Draw(); + } + + if (outline_visible) { + program.SetM(outline_transform); + outline.Draw(); + } - model.Draw(); + hud.Render(program); window.Flip(); }