]> git.localhorst.tv Git - blank.git/commitdiff
place and remove blocks via mouse
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 24 Feb 2015 07:47:09 +0000 (08:47 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 24 Feb 2015 17:10:52 +0000 (18:10 +0100)
src/app.cpp
src/app.hpp
src/geometry.cpp
src/geometry.hpp
src/world.cpp
src/world.hpp

index 5a5d6fba176376ab1052cec778afe9dd90c242e2..9ec9384f9ce749198af886d8fb16cff93c5d5ac3 100644 (file)
@@ -41,7 +41,12 @@ Application::Application()
 , 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::EnableDepthTest();
        GLContext::EnableBackfaceCulling();
@@ -210,6 +215,18 @@ void Application::HandleEvents() {
                                                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);
@@ -256,13 +273,36 @@ void Application::Update(int dt) {
        Ray aim = cam.Aim();
        int blkid;
        float dist;
-       if (chunk.Intersection(aim, glm::mat4(1.0f), &blkid, &dist)) {
+       glm::vec3 normal;
+       if (chunk.Intersection(aim, glm::mat4(1.0f), &blkid, &dist, &normal)) {
                glm::vec3 pos = Chunk::ToCoords(blkid);
                outline_visible = true;
                outline_transform = glm::translate(glm::mat4(1.0f), pos);
        } else {
                outline_visible = false;
        }
+
+       if (pick) {
+               if (outline_visible) {
+                       place_id = chunk.BlockAt(blkid).type->id;
+               }
+               pick = false;
+       }
+       if (remove) {
+               chunk.BlockAt(blkid).type = blockType[remove_id];
+               chunk.Invalidate();
+               remove = false;
+       }
+       if (place) {
+               if (outline_visible) {
+                       int next_blkid = Chunk::ToIndex(Chunk::ToCoords(blkid) + normal);
+                       if (next_blkid >= 0 && next_blkid < Chunk::Size()) {
+                               chunk.BlockAt(next_blkid).type = blockType[place_id];
+                               chunk.Invalidate();
+                       }
+               }
+               place = false;
+       }
 }
 
 void Application::Render() {
index 00154039d371cf9236d8b76afe11965ff1d44bdd..28c7536e440ec781926eb7af2b8a8099e4bfe6ed 100644 (file)
@@ -66,6 +66,10 @@ private:
        bool running;
 
        bool front, back, left, right, up, down;
+       bool place, remove, pick;
+
+       int remove_id;
+       int place_id;
 
 };
 
index c5f806997fae8cee4d9e26311ec0067dd607e808..df48ad3deac2c440f66d89f8fb69e69aac1e9b88 100644 (file)
@@ -1,31 +1,43 @@
 #include "geometry.hpp"
 
+#include <limits>
+
 
 namespace blank {
 
-bool Intersection(const Ray &ray, const AABB &aabb, const glm::mat4 &M, float *dist) {
+bool Intersection(
+       const Ray &ray,
+       const AABB &aabb,
+       const glm::mat4 &M,
+       float *dist,
+       glm::vec3 *normal
+) {
        float t_min = 0.0f;
        float t_max = 1.0e5f;
        const glm::vec3 aabb_pos(M[3].x, M[3].y, M[3].z);
        const glm::vec3 delta = aabb_pos - ray.orig;
 
+       glm::vec3 t1(t_min, t_min, t_min), t2(t_max, t_max, t_max);
+       bool x_swap = false, y_swap = false, z_swap = false;
+
        { // X
                const glm::vec3 xaxis(M[0].x, M[0].y, M[0].z);
                const float e = glm::dot(xaxis, delta);
                const float f = glm::dot(ray.dir, xaxis);
 
-               if (std::abs(f) > 0.001f) {
-                       float t1 = (e + aabb.min.x) / f;
-                       float t2 = (e + aabb.max.x) / f;
+               if (std::abs(f) > std::numeric_limits<float>::epsilon()) {
+                       t1.x = (e + aabb.min.x) / f;
+                       t2.x = (e + aabb.max.x) / f;
 
-                       if (t1 > t2) {
-                               std::swap(t1, t2);
+                       if (t1.x > t2.x) {
+                               std::swap(t1.x, t2.x);
+                               x_swap = true;
                        }
-                       if (t1 > t_min) {
-                               t_min = t1;
+                       if (t1.x > t_min) {
+                               t_min = t1.x;
                        }
-                       if (t2 < t_max) {
-                               t_max = t2;
+                       if (t2.x < t_max) {
+                               t_max = t2.x;
                        }
                        if (t_max < t_min) {
                                return false;
@@ -42,18 +54,19 @@ bool Intersection(const Ray &ray, const AABB &aabb, const glm::mat4 &M, float *d
                const float e = glm::dot(yaxis, delta);
                const float f = glm::dot(ray.dir, yaxis);
 
-               if (std::abs(f) > 0.001f) {
-                       float t1 = (e + aabb.min.y) / f;
-                       float t2 = (e + aabb.max.y) / f;
+               if (std::abs(f) > std::numeric_limits<float>::epsilon()) {
+                       t1.y = (e + aabb.min.y) / f;
+                       t2.y = (e + aabb.max.y) / f;
 
-                       if (t1 > t2) {
-                               std::swap(t1, t2);
+                       if (t1.y > t2.y) {
+                               std::swap(t1.y, t2.y);
+                               y_swap = true;
                        }
-                       if (t1 > t_min) {
-                               t_min = t1;
+                       if (t1.y > t_min) {
+                               t_min = t1.y;
                        }
-                       if (t2 < t_max) {
-                               t_max = t2;
+                       if (t2.y < t_max) {
+                               t_max = t2.y;
                        }
                        if (t_max < t_min) {
                                return false;
@@ -70,18 +83,19 @@ bool Intersection(const Ray &ray, const AABB &aabb, const glm::mat4 &M, float *d
                const float e = glm::dot(zaxis, delta);
                const float f = glm::dot(ray.dir, zaxis);
 
-               if (std::abs(f) > 0.001f) {
-                       float t1 = (e + aabb.min.z) / f;
-                       float t2 = (e + aabb.max.z) / f;
+               if (std::abs(f) > std::numeric_limits<float>::epsilon()) {
+                       t1.z = (e + aabb.min.z) / f;
+                       t2.z = (e + aabb.max.z) / f;
 
-                       if (t1 > t2) {
-                               std::swap(t1, t2);
+                       if (t1.z > t2.z) {
+                               std::swap(t1.z, t2.z);
+                               z_swap = true;
                        }
-                       if (t1 > t_min) {
-                               t_min = t1;
+                       if (t1.z > t_min) {
+                               t_min = t1.z;
                        }
-                       if (t2 < t_max) {
-                               t_max = t2;
+                       if (t2.z < t_max) {
+                               t_max = t2.z;
                        }
                        if (t_max < t_min) {
                                return false;
@@ -96,6 +110,19 @@ bool Intersection(const Ray &ray, const AABB &aabb, const glm::mat4 &M, float *d
        if (dist) {
                *dist = t_min;
        }
+       if (normal) {
+               if (t1.x > t1.y) {
+                       if (t1.x > t1.z) {
+                               *normal = glm::vec3(x_swap ? 1 : -1, 0, 0);
+                       } else {
+                               *normal = glm::vec3(0, 0, z_swap ? 1 : -1);
+                       }
+               } else if (t1.y > t1.z) {
+                       *normal = glm::vec3(0, y_swap ? 1 : -1, 0);
+               } else {
+                       *normal = glm::vec3(0, 0, z_swap ? 1 : -1);
+               }
+       }
        return true;
 }
 
index e8ead98de83bc75b1b32481cca16673371c966b3..bcc9c9a0918ef1dabfe270441818340bc1f45104 100644 (file)
@@ -23,7 +23,12 @@ struct Ray {
        glm::vec3 dir;
 };
 
-bool Intersection(const Ray &, const AABB &, const glm::mat4 &M, float *dist = nullptr);
+bool Intersection(
+       const Ray &,
+       const AABB &,
+       const glm::mat4 &M,
+       float *dist = nullptr,
+       glm::vec3 *normal = nullptr);
 
 }
 
index c958a65cf3144942f8d47af09576872fd48aae9c..e3c10b166d7af213a407ea076658155bfb1b5ce9 100644 (file)
@@ -89,7 +89,12 @@ void Chunk::Draw() {
 }
 
 
-bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float *dist) const {
+bool Chunk::Intersection(
+       const Ray &ray,
+       const glm::mat4 &M,
+       int *blkid,
+       float *dist,
+       glm::vec3 *normal) const {
        { // rough check
                const AABB bb{{0, 0, 0}, {Width(), Height(), Depth()}};
                if (!blank::Intersection(ray, bb, M)) {
@@ -97,7 +102,7 @@ bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float *
                }
        }
 
-       if (!blkid && !dist) {
+       if (!blkid && !dist && !normal) {
                return true;
        }
 
@@ -105,6 +110,7 @@ bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float *
        int id = 0;
        int closest_id = -1;
        float closest_dist = std::numeric_limits<float>::infinity();
+       glm::vec3 closest_normal(0, 1, 0);
        for (int z = 0; z < Depth(); ++z) {
                for (int y = 0; y < Height(); ++y) {
                        for (int x = 0; x < Width(); ++x, ++id) {
@@ -113,10 +119,12 @@ bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float *
                                }
                                const AABB bb{{x, y, z}, {x+1, y+1, z+1}};
                                float cur_dist;
-                               if (blank::Intersection(ray, bb, M, &cur_dist)) {
+                               glm::vec3 cur_norm;
+                               if (blank::Intersection(ray, bb, M, &cur_dist, &cur_norm)) {
                                        if (cur_dist < closest_dist) {
                                                closest_id = id;
                                                closest_dist = cur_dist;
+                                               closest_normal = cur_norm;
                                        }
                                }
                        }
@@ -133,6 +141,9 @@ bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float *
        if (dist) {
                *dist = closest_dist;
        }
+       if (normal) {
+               *normal = closest_normal;
+       }
        return true;
 }
 
index b7ed84bd5a71fbfa60415b70c9e84b74b72d8739..67ee355ccbc386d5d8fb08f75ec5c0b7d7fb27df 100644 (file)
@@ -93,10 +93,17 @@ public:
 
        void Invalidate() { dirty = true; }
 
-       Block &BlockAt(const glm::vec3 &pos) { return blocks[ToIndex(pos)]; }
-       const Block &BlockAt(const glm::vec3 &pos) const { return blocks[ToIndex(pos)]; }
-
-       bool Intersection(const Ray &, const glm::mat4 &M, int *blkid = nullptr, float *dist = nullptr) const;
+       Block &BlockAt(int index) { return blocks[index]; }
+       const Block &BlockAt(int index) const { return blocks[index]; }
+       Block &BlockAt(const glm::vec3 &pos) { return BlockAt(ToIndex(pos)); }
+       const Block &BlockAt(const glm::vec3 &pos) const { return BlockAt(ToIndex(pos)); }
+
+       bool Intersection(
+               const Ray &,
+               const glm::mat4 &M,
+               int *blkid = nullptr,
+               float *dist = nullptr,
+               glm::vec3 *normal = nullptr) const;
 
        void Draw();