]> git.localhorst.tv Git - blank.git/commitdiff
basic aiming
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 23 Feb 2015 17:18:01 +0000 (18:18 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Mon, 23 Feb 2015 17:18:01 +0000 (18:18 +0100)
src/app.cpp
src/camera.cpp
src/camera.hpp
src/geometry.cpp [new file with mode: 0644]
src/geometry.hpp [new file with mode: 0644]
src/world.cpp
src/world.hpp

index b398e9c20e4e032e7c6b9d59df18a39746e7239a..70c45d478c7284ffdf42866ed6900049c082771d 100644 (file)
@@ -1,5 +1,7 @@
 #include "app.hpp"
 
+#include "geometry.hpp"
+
 #include <iostream>
 #include <stdexcept>
 
@@ -234,6 +236,17 @@ void Application::Update(int dt) {
        cam.OrientationVelocity(vel);
 
        cam.Update(dt);
+
+       Ray aim = cam.Aim();
+       int blkid;
+       float dist;
+       if (chunk.Intersection(aim, glm::mat4(1.0f), &blkid, &dist)) {
+               glm::vec3 pos = Chunk::ToCoords(blkid);
+               std::cout << "pointing at: <" << pos.x << ", " << pos.y << ", " << pos.z << ">, "
+                       "distance: " << dist << std::endl;
+       } else {
+               std::cout << "pointing at: nothing" << std::endl;
+       }
 }
 
 void Application::Render() {
index fbf10bca2e1391a9f88522c0ba5ab9fe040475f1..8804d115b36574cdab2618fb441f0d1a50958696 100644 (file)
@@ -52,6 +52,15 @@ void Camera::Clip(float near, float far) {
        UpdateProjection();
 }
 
+Ray Camera::Aim() const {
+       const glm::mat4 inv_vp(glm::inverse(vp));
+       glm::vec4 from = inv_vp * glm::vec4(0.0f, 0.0f, -1.0f, 1.0f);
+       from /= from.w;
+       glm::vec4 to = inv_vp * glm::vec4(0.0f, 0.0f, 1.0f, 1.0f);
+       to /= to.w;
+       return Ray{ glm::vec3(from), glm::normalize(glm::vec3(to - from)) };
+}
+
 
 void Camera::Update(int dt) {
        FPSController::Update(dt);
index 7cdd5e527b1ca5ecc2e0c795dd5679907dd0d209..419922a39f1c3ee32578b847d5c21c7f31a3a434 100644 (file)
@@ -4,6 +4,7 @@
 #include <glm/glm.hpp>
 
 #include "controller.hpp"
+#include "geometry.hpp"
 
 
 namespace blank {
@@ -28,6 +29,8 @@ public:
        void Aspect(float w, float h);
        void Clip(float near, float far);
 
+       Ray Aim() const;
+
        const glm::mat4 &Projection() { return projection; }
        const glm::mat4 &View() { return view; }
 
diff --git a/src/geometry.cpp b/src/geometry.cpp
new file mode 100644 (file)
index 0000000..c5f8069
--- /dev/null
@@ -0,0 +1,102 @@
+#include "geometry.hpp"
+
+
+namespace blank {
+
+bool Intersection(const Ray &ray, const AABB &aabb, const glm::mat4 &M, float *dist) {
+       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;
+
+       { // 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 (t1 > t2) {
+                               std::swap(t1, t2);
+                       }
+                       if (t1 > t_min) {
+                               t_min = t1;
+                       }
+                       if (t2 < t_max) {
+                               t_max = t2;
+                       }
+                       if (t_max < t_min) {
+                               return false;
+                       }
+               } else {
+                       if (aabb.min.x - e > 0.0f || aabb.max.x < 0.0f) {
+                               return false;
+                       }
+               }
+       }
+
+       { // Y
+               const glm::vec3 yaxis(M[1].x, M[1].y, M[1].z);
+               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 (t1 > t2) {
+                               std::swap(t1, t2);
+                       }
+                       if (t1 > t_min) {
+                               t_min = t1;
+                       }
+                       if (t2 < t_max) {
+                               t_max = t2;
+                       }
+                       if (t_max < t_min) {
+                               return false;
+                       }
+               } else {
+                       if (aabb.min.y - e > 0.0f || aabb.max.y < 0.0f) {
+                               return false;
+                       }
+               }
+       }
+
+       { // Z
+               const glm::vec3 zaxis(M[2].x, M[2].y, M[2].z);
+               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 (t1 > t2) {
+                               std::swap(t1, t2);
+                       }
+                       if (t1 > t_min) {
+                               t_min = t1;
+                       }
+                       if (t2 < t_max) {
+                               t_max = t2;
+                       }
+                       if (t_max < t_min) {
+                               return false;
+                       }
+               } else {
+                       if (aabb.min.z - e > 0.0f || aabb.max.z < 0.0f) {
+                               return false;
+                       }
+               }
+       }
+
+       if (dist) {
+               *dist = t_min;
+       }
+       return true;
+}
+
+}
diff --git a/src/geometry.hpp b/src/geometry.hpp
new file mode 100644 (file)
index 0000000..e8ead98
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef BLANK_GEOMETRY_H_
+#define BLANK_GEOMETRY_H_
+
+#include <algorithm>
+#include <glm/glm.hpp>
+
+
+namespace blank {
+
+struct AABB {
+       glm::vec3 min;
+       glm::vec3 max;
+
+       void Adjust() {
+               if (max.x < min.x) std::swap(max.x, min.x);
+               if (max.y < min.y) std::swap(max.y, min.y);
+               if (max.z < min.z) std::swap(max.z, min.z);
+       }
+};
+
+struct Ray {
+       glm::vec3 orig;
+       glm::vec3 dir;
+};
+
+bool Intersection(const Ray &, const AABB &, const glm::mat4 &M, float *dist = nullptr);
+
+}
+
+#endif
index 96b48ee120d96ee4e79bec833936fb7ae310c2e8..c958a65cf3144942f8d47af09576872fd48aae9c 100644 (file)
@@ -1,5 +1,7 @@
 #include "world.hpp"
 
+#include <limits>
+
 
 namespace blank {
 
@@ -87,6 +89,54 @@ void Chunk::Draw() {
 }
 
 
+bool Chunk::Intersection(const Ray &ray, const glm::mat4 &M, int *blkid, float *dist) const {
+       { // rough check
+               const AABB bb{{0, 0, 0}, {Width(), Height(), Depth()}};
+               if (!blank::Intersection(ray, bb, M)) {
+                       return false;
+               }
+       }
+
+       if (!blkid && !dist) {
+               return true;
+       }
+
+       // TODO: should be possible to heavily optimize this
+       int id = 0;
+       int closest_id = -1;
+       float closest_dist = std::numeric_limits<float>::infinity();
+       for (int z = 0; z < Depth(); ++z) {
+               for (int y = 0; y < Height(); ++y) {
+                       for (int x = 0; x < Width(); ++x, ++id) {
+                               if (!blocks[id].type->visible) {
+                                       continue;
+                               }
+                               const AABB bb{{x, y, z}, {x+1, y+1, z+1}};
+                               float cur_dist;
+                               if (blank::Intersection(ray, bb, M, &cur_dist)) {
+                                       if (cur_dist < closest_dist) {
+                                               closest_id = id;
+                                               closest_dist = cur_dist;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (closest_id < 0) {
+               return false;
+       }
+
+       if (blkid) {
+               *blkid = closest_id;
+       }
+       if (dist) {
+               *dist = closest_dist;
+       }
+       return true;
+}
+
+
 int Chunk::VertexCount() const {
        // TODO: query blocks as soon as type shapes are implemented
        return Size() * 6 * 6;
index 58f7a25faeea7e8c8a622cf65d247a0bb022bf99..b7ed84bd5a71fbfa60415b70c9e84b74b72d8739 100644 (file)
@@ -2,6 +2,7 @@
 #define BLANK_WORLD_HPP_
 
 #include "model.hpp"
+#include "geometry.hpp"
 
 #include <vector>
 #include <GL/glew.h>
@@ -95,6 +96,8 @@ public:
        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;
+
        void Draw();
 
 private: