From f651ec76ac6be73387b3967b0d6fffc3d0ea8b49 Mon Sep 17 00:00:00 2001 From: Wellinator Date: Mon, 18 Jul 2022 16:11:18 -0300 Subject: [PATCH] feat: implements ray --- engine/inc/physics/ray.hpp | 98 ++++++++++++++++++++++++++++++++++++++ engine/src/physics/ray.cpp | 92 +++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 engine/inc/physics/ray.hpp create mode 100644 engine/src/physics/ray.cpp diff --git a/engine/inc/physics/ray.hpp b/engine/inc/physics/ray.hpp new file mode 100644 index 0000000..af6c2ab --- /dev/null +++ b/engine/inc/physics/ray.hpp @@ -0,0 +1,98 @@ +/* +# ______ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# 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: + /** + * Constructor create a ampty ray + * + */ + Ray(); + + /** + * Constructor + * @param origin The origin of the ray + * @param direction The direction of the ray (normalized Vec4) + * + */ + Ray(Vec4* origin, Vec4* direction); + ~Ray(); + + Vec4 origin; + Vec4 direction; + + // Methods + + /** + * Set origin and direction + */ + void set(Vec4 origin, Vec4 direction); + + /** + * Set origin only + */ + void setOrigin(Vec4 origin); + void setOrigin(const float& t_x, const float& t_y, const float& t_z); + + /** + * Set direction only + */ + void setDirection(Vec4 origin); + void setDirection(const float& t_x, const float& t_y, const float& t_z); + + /** + * Return Vec4 that is a given distance along this Ray + * @param t - the distance along the Ray to retrieve a position for. + */ + Vec4 at(float t); + + /** + * Return the distance from the Vec4 point to the origin + */ + float distanceToPoint(Vec4 point); + + /** + * Returns distance from origin to intersected mesh + */ + float distanceTo(const Vec4& v) const; + + /** + * Returns Vec4 of intersection position + * @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. + * + */ + u8 intersectBox(Vec4* minCorner, Vec4* maxCorner, float& distance); + + /** + * Returns distance from origin to intersected mesh + */ + inline const Vec4 getPosition() { return _position; }; + + /** + * Returns inverse direction + */ + Vec4 invDir(); + + private: + Vec4 _position; +}; + +} // namespace Tyra \ No newline at end of file diff --git a/engine/src/physics/ray.cpp b/engine/src/physics/ray.cpp new file mode 100644 index 0000000..e0bd436 --- /dev/null +++ b/engine/src/physics/ray.cpp @@ -0,0 +1,92 @@ +/* +# ______ ____ ___ +# | \/ ____| |___| +# | | | \ | | +#----------------------------------------------------------------------- +# 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(Vec4* origin, Vec4* direction) { + this->origin.set(origin->x, origin->y, origin->z); + this->direction.set(direction->x, direction->y, direction->z); +} + +Ray::~Ray() {} + +void Ray::set(Vec4 origin, Vec4 direction) { + this->origin.set(origin); + this->direction.set(direction); +} + +void Ray::setOrigin(Vec4 origin) { this->origin.set(origin); } + +void Ray::setOrigin(const float& t_x, const float& t_y, const float& t_z) { + this->origin.set(t_x, t_y, t_z); +} + +void Ray::setDirection(Vec4 direction) { this->direction.set(direction); } + +void Ray::setDirection(const float& t_x, const float& t_y, const float& t_z) { + this->direction.set(t_x, t_y, t_z); +} + +float Ray::distanceToPoint(Vec4 point) { return origin.distanceTo(point); } + +Vec4 Ray::at(float t) { return (this->direction * t) + this->origin; } + +u8 Ray::intersectBox(Vec4* minCorner, 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; +} + +Vec4 Ray::invDir() { + return Vec4(1 / this->direction.x, 1 / this->direction.y, + 1 / this->direction.z); +} + +} // Namespace Tyra \ No newline at end of file