diff --git a/include/engine/base_types.hpp b/include/engine/base_types.hpp new file mode 100644 index 0000000..a15d7d0 --- /dev/null +++ b/include/engine/base_types.hpp @@ -0,0 +1,64 @@ +/** + This file is a part of our_dick + Copyright (C) 2020 rexy712 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +#ifndef OUR_DICK_ENGINE_BASE_TYPES_HPP +#define OUR_DICK_ENGINE_BASE_TYPES_HPP + +#include "math/vec.hpp" + +namespace egn{ + + class line + { + public: + math::vec3 point1; + math::vec3 point2; + }; + + class aabb + { + public: + math::vec3 point1 = {}; + math::vec3 point2 = {}; + public: + aabb() = default; + aabb(const math::vec3& p1, const math::vec3& p2); + aabb(const aabb&) = default; + aabb(aabb&&) = default; + ~aabb() = default; + aabb& operator=(const aabb&) = default; + aabb& operator=(aabb&&) = default; + }; + class aabs + { + public: + math::vec3 point = {}; + float radius = 0.0f; + public: + aabs() = default; + aabs(float r); + aabs(const aabs&) = default; + aabs(aabs&&) = default; + ~aabs() = default; + aabs& operator=(const aabs&) = default; + aabs& operator=(aabs&&) = default; + }; + +} + +#endif diff --git a/include/engine/camera.hpp b/include/engine/camera.hpp index 31301d3..a1f5812 100644 --- a/include/engine/camera.hpp +++ b/include/engine/camera.hpp @@ -25,7 +25,7 @@ namespace egn{ - class camera_iface : public object + class camera_iface : public object_base { protected: enum update{ diff --git a/include/engine/object.hpp b/include/engine/object.hpp index fb72cc1..4f91aa3 100644 --- a/include/engine/object.hpp +++ b/include/engine/object.hpp @@ -21,10 +21,11 @@ #include "graphics/gl_include.hpp" //GLfloat #include "math/math.hpp" +#include "base_types.hpp" namespace egn{ - class object + class object_base { protected: enum update{ @@ -32,6 +33,7 @@ namespace egn{ SCALE_UPDATE = 1, TRANSLATION_UPDATE = 2, ROTATION_UPDATE = 4, + BOUNDING_VOLUME_UPDATE = 8, }; protected: math::vec3 m_position; //track current positon in world space @@ -41,15 +43,15 @@ namespace egn{ mutable int m_update_flag = NO_UPDATE; //whether or not to update the matrix upon access public: - object() = default; - explicit object(const math::vec3& position); - object(const math::vec3& position, const math::quaternion& orientation); - object(const object&) = default; - object(object&&) = default; - virtual ~object() = default; + object_base() = default; + explicit object_base(const math::vec3& position); + object_base(const math::vec3& position, const math::quaternion& orientation); + object_base(const object_base&) = default; + object_base(object_base&&) = default; + virtual ~object_base() = default; - object& operator=(const object&) = default; - object& operator=(object&&) = default; + object_base& operator=(const object_base&) = default; + object_base& operator=(object_base&&) = default; void translate(const math::vec3& distance); void rotate(const math::quaternion& distance); @@ -69,6 +71,67 @@ namespace egn{ void recalc_model_matrix()const; }; + class aabb_object : virtual public object_base + { + protected: + aabb m_model_bounding_box; //model coordinate bounding volume + mutable aabb m_world_bounding_box; //world coordinate bounding volume + public: + using object_base::object_base; + using object_base::operator=; + aabb_object(const math::vec3& position, + const math::vec3& aabb_p1, const math::vec3& aabb_p2); + aabb_object(const math::vec3& position, const math::quaternion& orientation, + const math::vec3& aabb_p1, const math::vec3& aabb_p2); + aabb_object() = default; + aabb_object(const aabb_object&) = default; + aabb_object(aabb_object&&) = default; + ~aabb_object() = default; + aabb_object& operator=(const aabb_object&) = default; + aabb_object& operator=(aabb_object&&) = default; + + const aabb& get_model_bounding_box()const; + const aabb& get_bounding_box()const; + }; + class aabs_object : virtual public object_base + { + protected: + aabs m_model_bounding_sphere; //model coordinate bounding volume + mutable aabs m_world_bounding_sphere; //world coordinate bounding volume + public: + using object_base::object_base; + using object_base::operator=; + aabs_object(const math::vec3& position, float aabs_r); + aabs_object(const math::vec3& position, const math::quaternion& orientation, + float aabs_r); + aabs_object() = default; + aabs_object(const aabs_object&) = default; + aabs_object(aabs_object&&) = default; + ~aabs_object() = default; + aabs_object& operator=(const aabs_object&) = default; + aabs_object& operator=(aabs_object&&) = default; + + const aabs& get_model_bounding_sphere()const; + const aabs& get_bounding_sphere()const; + }; + + bool check_collision(const aabb_object& l, const aabb_object& r); + bool check_collision(const aabb_object& l, const aabs_object& r); + bool check_collision(const aabs_object& l, const aabb_object& r); + bool check_collision(const aabs_object& l, const aabs_object& r); + bool check_collision(const aabb_object& o, const math::vec3& point); + bool check_collision(const aabs_object& o, const math::vec3& point); + bool check_collision(const aabb_object& o, const line& l); + bool check_collision(const aabs_object& o, const line& l); + bool check_collision(const aabb& l, const aabb& r); + bool check_collision(const aabb& l, const aabs& r); + bool check_collision(const aabs& l, const aabb& r); + bool check_collision(const aabs& l, const aabs& r); + bool check_collision(const aabb& l, const math::vec3& point); + bool check_collision(const aabs& l, const math::vec3& point); + bool check_collision(const aabb& o, const line& l); + bool check_collision(const aabs& o, const line& l); + } #endif diff --git a/include/renderable.hpp b/include/renderable.hpp index 2c73fba..7ec624c 100644 --- a/include/renderable.hpp +++ b/include/renderable.hpp @@ -19,17 +19,17 @@ #ifndef OUR_DICK_RENDERABLE_HPP #define OUR_DICK_RENDERABLE_HPP -#include "engine/object.hpp" #include "graphics/shader_program.hpp" +#include "engine/object.hpp" -class renderable_iface : public egn::object +class renderable_iface : virtual public egn::object_base { public: - using egn::object::object; - using egn::object::operator=; virtual ~renderable_iface() = default; virtual void render(gfx::shader_program&) = 0; }; +class aabb_renderable : public renderable_iface, public egn::aabb_object{}; +class aabs_renderable : public renderable_iface, public egn::aabb_object{}; #endif diff --git a/include/square.hpp b/include/square.hpp index a45379b..4145f21 100644 --- a/include/square.hpp +++ b/include/square.hpp @@ -24,10 +24,11 @@ #include "graphics/material.hpp" #include "graphics/shader_program.hpp" #include "renderable.hpp" +#include "engine/object.hpp" gfx::unified_mesh square_mesh(const gfx::material& blank, const gfx::material& o, const gfx::material& x); -class square : public renderable_iface +class square : public aabb_renderable { public: enum class value{ diff --git a/include/util/minmax.hpp b/include/util/minmax.hpp index f05cf83..d01c316 100644 --- a/include/util/minmax.hpp +++ b/include/util/minmax.hpp @@ -37,20 +37,26 @@ namespace util{ } }; - template - static constexpr T max(const T& left, const T& right){ + template + static constexpr const T& max(const T& left, const T& right, Args&&... args){ + if constexpr(sizeof...(args) > 0){ + return left > right ? max(left, std::forward(args)...) : max(right, std::forward(args)...); + } return left > right ? left : right; } - template - static constexpr T min(const T& left, const T& right){ + template + static constexpr const T& min(const T& left, const T& right, Args&&... args){ + if constexpr(sizeof...(args) > 0){ + return left < right ? min(left, std::forward(args)...) : min(right, std::forward(args)...); + } return left < right ? left : right; } template - static constexpr T max(const T& left, const T& right, Compare cmp){ + static constexpr T maxc(const T& left, const T& right, Compare cmp){ return cmp(left, right) ? left : right; } template - static constexpr T min(const T& left, const T& right, Compare cmp){ + static constexpr T minc(const T& left, const T& right, Compare cmp){ return cmp(left, right) ? left : right; } diff --git a/src/engine/base_types.cpp b/src/engine/base_types.cpp new file mode 100644 index 0000000..9d6f954 --- /dev/null +++ b/src/engine/base_types.cpp @@ -0,0 +1,30 @@ +/** + This file is a part of our_dick + Copyright (C) 2020 rexy712 + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +#include "engine/base_types.hpp" + +namespace egn{ + + aabb::aabb(const math::vec3& p1, const math::vec3& p2): + point1(p1), + point2(p2){} + + + aabs::aabs(float r): + radius(r){} +} diff --git a/src/engine/camera.cpp b/src/engine/camera.cpp index 599a8aa..c065a90 100644 --- a/src/engine/camera.cpp +++ b/src/engine/camera.cpp @@ -27,11 +27,11 @@ namespace egn{ m_near(n), m_far(f){} void camera_iface::set_position(const math::vec3& pos){ - object::set_position(pos); + object_base::set_position(pos); m_update_flag |= VIEW_UPDATE; } void camera_iface::set_orientation(const math::quaternion& orient){ - object::set_orientation(orient); + object_base::set_orientation(orient); m_update_flag |= VIEW_UPDATE; } const math::mat4& camera_iface::get_projection_matrix()const{ diff --git a/src/engine/object.cpp b/src/engine/object.cpp index 624a408..c8908c0 100644 --- a/src/engine/object.cpp +++ b/src/engine/object.cpp @@ -18,27 +18,28 @@ #include "engine/object.hpp" #include "config.hpp" +#include "util/minmax.hpp" namespace egn{ - object::object(const math::vec3& position): + object_base::object_base(const math::vec3& position): m_position(position){} - object::object(const math::vec3& position, const math::quaternion& orientation): + object_base::object_base(const math::vec3& position, const math::quaternion& orientation): m_position(position), m_orientation(orientation){} - void object::translate(const math::vec3& distance){ + void object_base::translate(const math::vec3& distance){ set_position(m_position + distance); } - void object::rotate(const math::quaternion& distance){ + void object_base::rotate(const math::quaternion& distance){ set_orientation(m_orientation * distance); } - void object::scale(const math::vec3& distance){ + void object_base::scale(const math::vec3& distance){ set_scale(math::vec3{m_scale[0] * distance[0], m_scale[1] * distance[1], m_scale[2] * distance[2]}); } - void object::look_at(const math::vec3& targ, const math::vec3& up){ + void object_base::look_at(const math::vec3& targ, const math::vec3& up){ math::vec3 front((m_position - targ).normalize()); math::vec3 right(math::cross(up, front)); math::vec3 true_up(math::cross(front, right)); @@ -46,36 +47,36 @@ namespace egn{ right[1], true_up[1], front[1], right[2], true_up[2], front[2]}}); } - void object::set_position(const math::vec3& pos){ - m_update_flag |= TRANSLATION_UPDATE; + void object_base::set_position(const math::vec3& pos){ + m_update_flag |= (TRANSLATION_UPDATE | BOUNDING_VOLUME_UPDATE); m_position = pos; } - void object::set_orientation(const math::quaternion& orient){ - m_update_flag |= ROTATION_UPDATE; + void object_base::set_orientation(const math::quaternion& orient){ + m_update_flag |= (ROTATION_UPDATE | BOUNDING_VOLUME_UPDATE); m_orientation = orient; } - void object::set_scale(const math::vec3& scale){ - m_update_flag |= SCALE_UPDATE; + void object_base::set_scale(const math::vec3& scale){ + m_update_flag |= (SCALE_UPDATE | BOUNDING_VOLUME_UPDATE); m_scale = scale; } - const math::mat4& object::get_model_matrix()const{ + const math::mat4& object_base::get_model_matrix()const{ if(m_update_flag & (SCALE_UPDATE | ROTATION_UPDATE | TRANSLATION_UPDATE)){ recalc_model_matrix(); m_update_flag &= (~(SCALE_UPDATE | ROTATION_UPDATE | TRANSLATION_UPDATE)); } return m_model_matrix; } - const math::vec3& object::get_position()const{ + const math::vec3& object_base::get_position()const{ return m_position; } - const math::vec3& object::get_scale()const{ + const math::vec3& object_base::get_scale()const{ return m_scale; } - const math::quaternion& object::get_orientation()const{ + const math::quaternion& object_base::get_orientation()const{ return m_orientation; } - void object::recalc_model_matrix()const{ + void object_base::recalc_model_matrix()const{ debug_print_verbose("Rebuilding model matrix\n"); m_model_matrix = m_orientation.to_mat4(); m_model_matrix.get(3, 0) = m_position[0]; @@ -83,4 +84,53 @@ namespace egn{ m_model_matrix.get(3, 2) = m_position[2]; } + aabb_object::aabb_object(const math::vec3& position, + const math::vec3& aabb_p1, const math::vec3& aabb_p2): + object_base(position), + m_model_bounding_box(aabb_p1, aabb_p2), + m_world_bounding_box(m_model_bounding_box){} + aabb_object::aabb_object(const math::vec3& position, const math::quaternion& orientation, + const math::vec3& aabb_p1, const math::vec3& aabb_p2): + object_base(position, orientation), + m_model_bounding_box(aabb_p1, aabb_p2), + m_world_bounding_box(m_model_bounding_box){} + const aabb& aabb_object::get_model_bounding_box()const{ + return m_model_bounding_box; + } + const aabb& aabb_object::get_bounding_box()const{ + if(m_update_flag){ + recalc_model_matrix(); + m_world_bounding_box.point1 = m_model_matrix * math::vec4(m_model_bounding_box.point1, 1.0f); + m_world_bounding_box.point2 = m_model_matrix * math::vec4(m_model_bounding_box.point2, 1.0f); + m_update_flag &= ~BOUNDING_VOLUME_UPDATE; + } + return m_world_bounding_box; + } + + aabs_object::aabs_object(const math::vec3& position, float aabs_r): + object_base(position), + m_model_bounding_sphere(aabs_r), + m_world_bounding_sphere(m_model_bounding_sphere){} + aabs_object::aabs_object(const math::vec3& position, const math::quaternion& orientation, + float aabs_r): + object_base(position, orientation), + m_model_bounding_sphere(aabs_r), + m_world_bounding_sphere(m_model_bounding_sphere){} + const aabs& aabs_object::get_model_bounding_sphere()const{ + return m_model_bounding_sphere; + } + const aabs& aabs_object::get_bounding_sphere()const{ + if(m_update_flag){ + math::mat4 t_mat{1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + m_position.x(), m_position.y(), m_position.z(), 1}; + m_world_bounding_sphere.point = t_mat * math::vec4(m_model_bounding_sphere.point, 1.0f); + m_world_bounding_sphere.radius *= util::max(m_scale.x(), m_scale.y(), m_scale.z()); + m_update_flag &= ~BOUNDING_VOLUME_UPDATE; + } + return m_world_bounding_sphere; + } + + }