diff --git a/engine/inc/physics/ray.hpp b/engine/inc/physics/ray.hpp new file mode 100644 index 0000000..c940145 --- /dev/null +++ b/engine/inc/physics/ray.hpp @@ -0,0 +1,77 @@ +/* +# ______ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2020-2022, tyra - https://github.com/h4570/tyra +# Licenced under Apache License 2.0 +# Wellington Carvalho +*/ + +#include "math/vec4.hpp" + +#pragma once + +namespace Tyra { + +/** + * Class for raycasting. + */ +class Ray { + public: + /** @brief Constructor create a ampty ray */ + Ray(); + + /** + * @param origin The origin of the ray + * @param direction The direction of the ray (normalized Vec4) + */ + Ray(const Vec4& origin, const Vec4& direction); + ~Ray(); + + // Methods + + /** + * @param origin Vec4 starting point of the ray; + * @param direction Vec4 normalized vector pointing to direction; + */ + void set(const Vec4& origin, const Vec4& direction); + + /** + * @brief Set origin of the ray; + * @param origin Vec4 starting point of the ray; + */ + void setOrigin(const Vec4& origin); + + /** + * @brief Set direction of the ray; + * @param direction Vec4 normalized vector pointing to direction; + */ + void setDirection(const Vec4& direction); + + /** + * @return Vec4 that is a given distance along this Ray + * @param t - the distance along the Ray to retrieve a position for. + */ + Vec4 at(const float& t); + + /** @return Distance from the Vec4 point to the origin */ + float distanceToPoint(const Vec4& point); + + /** + * @param minCorner - pointer to min corner position. (bottom left) + * @param maxCorner - pointer to max corner position. (top right) + * @param distance - the box to intersect with. + * @return Vec4 point of intersection + */ + u8 intersectBox(const Vec4& minCorner, const Vec4& maxCorner, float& distance); + + /** Returns inverse direction */ + const Vec4 invDir(); + + private: + Vec4 _origin; + Vec4 _direction; +}; + +} // namespace Tyra \ No newline at end of file diff --git a/engine/inc/renderer/3d/bbox/bbox.hpp b/engine/inc/renderer/3d/bbox/bbox.hpp index 35fdd0c..57777d1 100644 --- a/engine/inc/renderer/3d/bbox/bbox.hpp +++ b/engine/inc/renderer/3d/bbox/bbox.hpp @@ -41,6 +41,17 @@ class BBox : public CoreBBox { /** @returns the bottom face (nearer on y-axis) */ const BBoxFace& getBottomFace() { return _bottomFace; } + /** @returns the lower (x, y, z) boundary of the box. */ + Vec4 min(); + /** @returns the upper (x, y, z) boundary of the box. */ + Vec4 max(); + /** + * @param res_min Vec4 to store the min result + * @param res_max Vec4 to store the min result + * @brief Calc and stores the min and max points of box at a single loop + * */ + void getMinMax(Vec4* res_min, Vec4* res_max); + protected: float _height, _depth, _width; Vec4 _centerVector; diff --git a/engine/inc/renderer/core/3d/bbox/core_bbox.hpp b/engine/inc/renderer/core/3d/bbox/core_bbox.hpp index 7e0c4b1..b4314df 100644 --- a/engine/inc/renderer/core/3d/bbox/core_bbox.hpp +++ b/engine/inc/renderer/core/3d/bbox/core_bbox.hpp @@ -36,6 +36,9 @@ class CoreBBox { void print(const std::string& name) const { print(name.c_str()); } std::string getPrint(const char* name = nullptr) const; + CoreBBoxFrustum isInFrustum(const Plane* frustumPlanes, const M4x4& model, + const float* margins = nullptr) const; + protected: Vec4 _vertices[8]; }; diff --git a/engine/inc/renderer/core/3d/bbox/render_bbox.hpp b/engine/inc/renderer/core/3d/bbox/render_bbox.hpp index e45f092..b4904b0 100644 --- a/engine/inc/renderer/core/3d/bbox/render_bbox.hpp +++ b/engine/inc/renderer/core/3d/bbox/render_bbox.hpp @@ -25,9 +25,6 @@ class RenderBBox : public CoreBBox { explicit RenderBBox(const std::vector& t_bboxes, const u32& startIndex, const u32& stopIndex); - CoreBBoxFrustum isInFrustum(const Plane* frustumPlanes, const M4x4& model, - const float* margins = nullptr) const; - CoreBBoxFrustum clipIsInFrustum(const Plane* frustumPlanes, const M4x4& model) const; }; diff --git a/engine/src/physics/ray.cpp b/engine/src/physics/ray.cpp new file mode 100644 index 0000000..333c701 --- /dev/null +++ b/engine/src/physics/ray.cpp @@ -0,0 +1,89 @@ +/* +# ______ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# Copyright 2020-2022, tyra - https://github.com/h4570/tyra +# Licenced under Apache License 2.0 +# Wellinator Carvalho +*/ + +#include "physics/ray.hpp" +#include +#include +#include + +namespace Tyra { + +Ray::Ray() {} +Ray::Ray(const Vec4& origin, const Vec4& direction) { + this->_origin.set(origin); + this->_direction.set(direction); +} + +Ray::~Ray() {} + +void Ray::set(const Vec4& origin, const Vec4& direction) { + this->_origin.set(origin); + this->_direction.set(direction); +} + +void Ray::setOrigin(const Vec4& origin) { this->_origin.set(origin); } + +void Ray::setDirection(const Vec4& direction) { + this->_direction.set(direction); +} + +Vec4 Ray::at(const float& t) { return (this->_direction * t) + this->_origin; } + +float Ray::distanceToPoint(const Vec4& point) { + return this->_origin.distanceTo(point); +} + +u8 Ray::intersectBox(const Vec4& minCorner, const Vec4& maxCorner, + float& distance) { + float tmin, tmax, tymin, tymax, tzmin, tzmax; + Vec4 invDir = this->invDir(); + invDir.normalize(); + + tmin = (minCorner.x - this->_origin.x) * invDir.x; + tmax = (maxCorner.x - this->_origin.x) * invDir.x; + tymin = (minCorner.y - this->_origin.y) * invDir.y; + tymax = (maxCorner.y - this->_origin.y) * invDir.y; + + if ((tmin > tymax) || (tymin > tmax)) { + distance = -1.0f; + return 0; + } + + if (tymin > tmin) tmin = tymin; + + if (tymax < tmax) tmax = tymax; + + tzmin = (minCorner.z - this->_origin.z) * invDir.z; + tzmax = (maxCorner.z - this->_origin.z) * invDir.z; + + if ((tmin > tzmax) || (tzmin > tmax)) { + distance = -1.0f; + return 0; + } + + if (tzmin > tmin) tmin = tzmin; + + if (tzmax < tmax) tmax = tzmax; + + if (tmax < 0) { + distance = -1.0f; + return 0; + } + + distance = tmin >= 0 ? tmin : tmax; + return 1; +} + +const Vec4 Ray::invDir() { + return Vec4(1 / this->_direction.x, 1 / this->_direction.y, + 1 / this->_direction.z, 1); +} + +} // Namespace Tyra \ No newline at end of file diff --git a/engine/src/renderer/3d/bbox/bbox.cpp b/engine/src/renderer/3d/bbox/bbox.cpp index 64e5d20..db8b4ad 100644 --- a/engine/src/renderer/3d/bbox/bbox.cpp +++ b/engine/src/renderer/3d/bbox/bbox.cpp @@ -50,4 +50,68 @@ void BBox::setData() { _bottomFace = BBoxFace(_vertices[0], _vertices[5], _vertices[0].y); } +Vec4 BBox::min() { + Vec4 temp, _min; + u8 isInitialized = 0; + + const Vec4* vertices = getVertices(); + for (u8 i = 0; i < 8; i++) { + temp.set(vertices[i].x, vertices[i].y, vertices[i].z, 1.0F); + if (isInitialized == 0) { + isInitialized = 1; + _min.set(temp); + } + + if (_min.x > temp.x) _min.x = temp.x; + if (_min.y > temp.y) _min.y = temp.y; + if (_min.z > temp.z) _min.z = temp.z; + } + + return _min; +} + +Vec4 BBox::max() { + Vec4 temp, _max; + u8 isInitialized = 0; + + const Vec4* vertices = getVertices(); + for (u8 i = 0; i < 8; i++) { + temp.set(vertices[i].x, vertices[i].y, vertices[i].z, 1.0F); + if (isInitialized == 0) { + isInitialized = 1; + _max.set(temp); + } + + if (temp.x > _max.x) _max.x = temp.x; + if (temp.y > _max.y) _max.y = temp.y; + if (temp.z > _max.z) _max.z = temp.z; + } + + return _max; +} + +void BBox::getMinMax(Vec4* res_min, Vec4* res_max) { + Vec4 temp = Vec4(); + + u8 isInitialized = 0; + const Vec4* vertices = getVertices(); + for (u8 i = 0; i < 8; i++) { + temp.set(vertices[i].x, vertices[i].y, vertices[i].z, 1.0F); + if (isInitialized == 0) { + isInitialized = 1; + res_min->set(temp); + res_max->set(temp); + } + + if (res_min->x > temp.x) res_min->x = temp.x; + if (temp.x > res_max->x) res_max->x = temp.x; + + if (res_min->y > temp.y) res_min->y = temp.y; + if (temp.y > res_max->y) res_max->y = temp.y; + + if (res_min->z > temp.z) res_min->z = temp.z; + if (temp.z > res_max->z) res_max->z = temp.z; + } +} + } // namespace Tyra diff --git a/engine/src/renderer/core/3d/bbox/core_bbox.cpp b/engine/src/renderer/core/3d/bbox/core_bbox.cpp index 7341784..4903314 100644 --- a/engine/src/renderer/core/3d/bbox/core_bbox.cpp +++ b/engine/src/renderer/core/3d/bbox/core_bbox.cpp @@ -166,4 +166,37 @@ std::string CoreBBox::getPrint(const char* name) const { return res.str(); } +CoreBBoxFrustum CoreBBox::isInFrustum(const Plane* frustumPlanes, + const M4x4& model, + const float* margins) const { + CoreBBoxFrustum result = IN_FRUSTUM; + Vec4 boxCalcTemp; + u8 boxIn = 0, boxOut = 0; + + for (u8 i = 0; i < 6; i++) { + const auto margin = margins == nullptr ? 0.0F : margins[i]; + boxOut = 0; + boxIn = 0; + // for each corner of the box do ... + // get out of the cycle as soon as a box as corners + // both inside and out of the frustum + for (u8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++) { + boxCalcTemp = model * _vertices[y]; + + auto isOut = frustumPlanes[i].distanceTo(boxCalcTemp) < margin; + + if (isOut) + boxOut++; + else + boxIn++; + } + // if all corners are out + if (!boxIn) + return OUTSIDE_FRUSTUM; + else if (boxOut) + result = PARTIALLY_IN_FRUSTUM; + } + return result; +} + } // namespace Tyra diff --git a/engine/src/renderer/core/3d/bbox/render_bbox.cpp b/engine/src/renderer/core/3d/bbox/render_bbox.cpp index dc1465b..1d2cd1a 100644 --- a/engine/src/renderer/core/3d/bbox/render_bbox.cpp +++ b/engine/src/renderer/core/3d/bbox/render_bbox.cpp @@ -58,37 +58,4 @@ CoreBBoxFrustum RenderBBox::clipIsInFrustum(const Plane* frustumPlanes, return isInFrustum(frustumPlanes, model, margins); // Let's check it again } -CoreBBoxFrustum RenderBBox::isInFrustum(const Plane* frustumPlanes, - const M4x4& model, - const float* margins) const { - CoreBBoxFrustum result = IN_FRUSTUM; - Vec4 boxCalcTemp; - u8 boxIn = 0, boxOut = 0; - - for (u8 i = 0; i < 6; i++) { - const auto margin = margins == nullptr ? 0.0F : margins[i]; - boxOut = 0; - boxIn = 0; - // for each corner of the box do ... - // get out of the cycle as soon as a box as corners - // both inside and out of the frustum - for (u8 y = 0; y < 8 && (boxIn == 0 || boxOut == 0); y++) { - boxCalcTemp = model * _vertices[y]; - - auto isOut = frustumPlanes[i].distanceTo(boxCalcTemp) < margin; - - if (isOut) - boxOut++; - else - boxIn++; - } - // if all corners are out - if (!boxIn) - return OUTSIDE_FRUSTUM; - else if (boxOut) - result = PARTIALLY_IN_FRUSTUM; - } - return result; -} - } // namespace Tyra