Work on bounding volumes

This commit is contained in:
rexy712 2020-10-18 10:00:55 -07:00
parent 05efb3c006
commit 0959517d08
9 changed files with 254 additions and 40 deletions

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<float> point1;
math::vec3<float> point2;
};
class aabb
{
public:
math::vec3<float> point1 = {};
math::vec3<float> point2 = {};
public:
aabb() = default;
aabb(const math::vec3<float>& p1, const math::vec3<float>& p2);
aabb(const aabb&) = default;
aabb(aabb&&) = default;
~aabb() = default;
aabb& operator=(const aabb&) = default;
aabb& operator=(aabb&&) = default;
};
class aabs
{
public:
math::vec3<float> 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

View File

@ -25,7 +25,7 @@
namespace egn{
class camera_iface : public object
class camera_iface : public object_base
{
protected:
enum update{

View File

@ -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<GLfloat> 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<GLfloat>& position);
object(const math::vec3<GLfloat>& position, const math::quaternion<GLfloat>& orientation);
object(const object&) = default;
object(object&&) = default;
virtual ~object() = default;
object_base() = default;
explicit object_base(const math::vec3<GLfloat>& position);
object_base(const math::vec3<GLfloat>& position, const math::quaternion<GLfloat>& 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<GLfloat>& distance);
void rotate(const math::quaternion<GLfloat>& 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<GLfloat>& position,
const math::vec3<GLfloat>& aabb_p1, const math::vec3<GLfloat>& aabb_p2);
aabb_object(const math::vec3<GLfloat>& position, const math::quaternion<GLfloat>& orientation,
const math::vec3<GLfloat>& aabb_p1, const math::vec3<GLfloat>& 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<GLfloat>& position, float aabs_r);
aabs_object(const math::vec3<GLfloat>& position, const math::quaternion<GLfloat>& 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<float>& point);
bool check_collision(const aabs_object& o, const math::vec3<float>& 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<float>& point);
bool check_collision(const aabs& l, const math::vec3<float>& point);
bool check_collision(const aabb& o, const line& l);
bool check_collision(const aabs& o, const line& l);
}
#endif

View File

@ -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

View File

@ -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{

View File

@ -37,20 +37,26 @@ namespace util{
}
};
template<typename T>
static constexpr T max(const T& left, const T& right){
template<typename T, typename... Args>
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>(args)...) : max(right, std::forward<Args>(args)...);
}
return left > right ? left : right;
}
template<typename T>
static constexpr T min(const T& left, const T& right){
template<typename T, typename... Args>
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>(args)...) : min(right, std::forward<Args>(args)...);
}
return left < right ? left : right;
}
template<typename T, typename Compare>
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<typename T, typename Compare>
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;
}

30
src/engine/base_types.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "engine/base_types.hpp"
namespace egn{
aabb::aabb(const math::vec3<float>& p1, const math::vec3<float>& p2):
point1(p1),
point2(p2){}
aabs::aabs(float r):
radius(r){}
}

View File

@ -27,11 +27,11 @@ namespace egn{
m_near(n), m_far(f){}
void camera_iface::set_position(const math::vec3<GLfloat>& pos){
object::set_position(pos);
object_base::set_position(pos);
m_update_flag |= VIEW_UPDATE;
}
void camera_iface::set_orientation(const math::quaternion<GLfloat>& orient){
object::set_orientation(orient);
object_base::set_orientation(orient);
m_update_flag |= VIEW_UPDATE;
}
const math::mat4<GLfloat>& camera_iface::get_projection_matrix()const{

View File

@ -18,27 +18,28 @@
#include "engine/object.hpp"
#include "config.hpp"
#include "util/minmax.hpp"
namespace egn{
object::object(const math::vec3<GLfloat>& position):
object_base::object_base(const math::vec3<GLfloat>& position):
m_position(position){}
object::object(const math::vec3<GLfloat>& position, const math::quaternion<GLfloat>& orientation):
object_base::object_base(const math::vec3<GLfloat>& position, const math::quaternion<GLfloat>& orientation):
m_position(position),
m_orientation(orientation){}
void object::translate(const math::vec3<GLfloat>& distance){
void object_base::translate(const math::vec3<GLfloat>& distance){
set_position(m_position + distance);
}
void object::rotate(const math::quaternion<GLfloat>& distance){
void object_base::rotate(const math::quaternion<GLfloat>& distance){
set_orientation(m_orientation * distance);
}
void object::scale(const math::vec3<GLfloat>& distance){
void object_base::scale(const math::vec3<GLfloat>& distance){
set_scale(math::vec3<GLfloat>{m_scale[0] * distance[0],
m_scale[1] * distance[1],
m_scale[2] * distance[2]});
}
void object::look_at(const math::vec3<GLfloat>& targ, const math::vec3<GLfloat>& up){
void object_base::look_at(const math::vec3<GLfloat>& targ, const math::vec3<GLfloat>& up){
math::vec3<GLfloat> front((m_position - targ).normalize());
math::vec3<GLfloat> right(math::cross(up, front));
math::vec3<GLfloat> 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<GLfloat>& pos){
m_update_flag |= TRANSLATION_UPDATE;
void object_base::set_position(const math::vec3<GLfloat>& pos){
m_update_flag |= (TRANSLATION_UPDATE | BOUNDING_VOLUME_UPDATE);
m_position = pos;
}
void object::set_orientation(const math::quaternion<GLfloat>& orient){
m_update_flag |= ROTATION_UPDATE;
void object_base::set_orientation(const math::quaternion<GLfloat>& orient){
m_update_flag |= (ROTATION_UPDATE | BOUNDING_VOLUME_UPDATE);
m_orientation = orient;
}
void object::set_scale(const math::vec3<GLfloat>& scale){
m_update_flag |= SCALE_UPDATE;
void object_base::set_scale(const math::vec3<GLfloat>& scale){
m_update_flag |= (SCALE_UPDATE | BOUNDING_VOLUME_UPDATE);
m_scale = scale;
}
const math::mat4<GLfloat>& object::get_model_matrix()const{
const math::mat4<GLfloat>& 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<GLfloat>& object::get_position()const{
const math::vec3<GLfloat>& object_base::get_position()const{
return m_position;
}
const math::vec3<GLfloat>& object::get_scale()const{
const math::vec3<GLfloat>& object_base::get_scale()const{
return m_scale;
}
const math::quaternion<GLfloat>& object::get_orientation()const{
const math::quaternion<GLfloat>& 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<GLfloat>& position,
const math::vec3<GLfloat>& aabb_p1, const math::vec3<GLfloat>& 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<GLfloat>& position, const math::quaternion<GLfloat>& orientation,
const math::vec3<GLfloat>& aabb_p1, const math::vec3<GLfloat>& 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<float>(m_model_bounding_box.point1, 1.0f);
m_world_bounding_box.point2 = m_model_matrix * math::vec4<float>(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<GLfloat>& 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<GLfloat>& position, const math::quaternion<GLfloat>& 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<float> 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<float>(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;
}
}