From 1849d31d7c60507b5314dd59655839c5c620bb6d Mon Sep 17 00:00:00 2001 From: RaveYard <29225776+MrRaveYard@users.noreply.github.com> Date: Thu, 31 Aug 2023 10:04:35 +0200 Subject: [PATCH] Add bounds.cpp from ZDRay --- src/CMakeLists.txt | 1 + src/common/utility/bounds.cpp | 379 ++++++++++++++++++++++++++++++++++ src/common/utility/bounds.h | 65 ++++++ 3 files changed, 445 insertions(+) create mode 100644 src/common/utility/bounds.cpp create mode 100644 src/common/utility/bounds.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e3bd916cb8..1f3bdc9d00 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1062,6 +1062,7 @@ set (PCH_SOURCES common/utility/s_playlist.cpp common/utility/name.cpp common/utility/r_memory.cpp + common/utility/bounds.cpp common/thirdparty/base64.cpp common/thirdparty/md5.cpp common/thirdparty/superfasthash.cpp diff --git a/src/common/utility/bounds.cpp b/src/common/utility/bounds.cpp new file mode 100644 index 0000000000..8b1b30b8d9 --- /dev/null +++ b/src/common/utility/bounds.cpp @@ -0,0 +1,379 @@ +//----------------------------------------------------------------------------- +// Note: this is a modified version of dlight. It is not the original software. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2013-2014 Samuel Villarreal +// svkaiser@gmail.com +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#include +#include + +#include "bounds.h" + +#define M_INFINITY 1e30f + +BBox::BBox() +{ + Clear(); +} + +BBox::BBox(const FVector3 &vMin, const FVector3 &vMax) +{ + this->min = vMin; + this->max = vMax; +} + +void BBox::Clear() +{ + min = FVector3(M_INFINITY, M_INFINITY, M_INFINITY); + max = FVector3(-M_INFINITY, -M_INFINITY, -M_INFINITY); +} + +void BBox::AddPoint(const FVector3 &vec) +{ + float lowx = min.X; + float lowy = min.Y; + float lowz = min.Z; + float hix = max.X; + float hiy = max.Y; + float hiz = max.Z; + + if (vec.X < lowx) { lowx = vec.X; } + if (vec.Y < lowy) { lowy = vec.Y; } + if (vec.Z < lowz) { lowz = vec.Z; } + if (vec.X > hix) { hix = vec.X; } + if (vec.Y > hiy) { hiy = vec.Y; } + if (vec.Z > hiz) { hiz = vec.Z; } + + min = FVector3(lowx, lowy, lowz); + max = FVector3(hix, hiy, hiz); +} + +float BBox::Radius() const +{ + int i; + float r = 0; + float r1; + float r2; + + for (i = 0; i < 3; i++) + { + r1 = fabsf(min[i]); + r2 = fabsf(max[i]); + + if (r1 > r2) + { + r += r1 * r1; + } + else + { + r += r2 * r2; + } + } + + return sqrtf(r); +} + +bool BBox::PointInside(const FVector3 &vec) const +{ + return !(vec[0] < min[0] || vec[1] < min[1] || vec[2] < min[2] || + vec[0] > max[0] || vec[1] > max[1] || vec[2] > max[2]); +} + +bool BBox::IntersectingBox(const BBox &box) const +{ + return !(box.max[0] < min[0] || box.max[1] < min[1] || box.max[2] < min[2] || + box.min[0] > max[0] || box.min[1] > max[1] || box.min[2] > max[2]); +} + +bool BBox::IntersectingBox2D(const BBox &box) const +{ + return !(box.max[0] < min[0] || box.max[2] < min[2] || + box.min[0] > max[0] || box.min[2] > max[2]); +} + +float BBox::DistanceToPlane(Plane &plane) +{ + throw "unimplemented"; + return 0; + /*FVector3 c; + float distStart; + float distEnd; + float dist = 0; + + c = Center(); + + distStart = plane.Distance(c); + distEnd = fabs((max.X - c.X) * plane.a) + + fabs((max.Y - c.Y) * plane.b) + + fabs((max.Z - c.Z) * plane.c); + + dist = distStart - distEnd; + + if (dist > 0) + { + // in front + return dist; + } + + dist = distStart + distEnd; + + if (dist < 0) + { + // behind + return dist; + } + + return 0;*/ +} + +BBox BBox::operator+(const float radius) const +{ + FVector3 vmin = min; + FVector3 vmax = max; + + vmin.X -= radius; + vmin.Y -= radius; + vmin.Z -= radius; + + vmax.X += radius; + vmax.Y += radius; + vmax.Z += radius; + + return BBox(vmin, vmax); +} + +BBox &BBox::operator+=(const float radius) +{ + min.X -= radius; + min.Y -= radius; + min.Z -= radius; + max.X += radius; + max.Y += radius; + max.Z += radius; + return *this; +} + +BBox BBox::operator+(const FVector3 &vec) const +{ + FVector3 vmin = min; + FVector3 vmax = max; + + vmin.X += vec.X; + vmin.Y += vec.Y; + vmin.Z += vec.Z; + + vmax.X += vec.X; + vmax.Y += vec.Y; + vmax.Z += vec.Z; + + return BBox(vmin, vmax); +} + +BBox BBox::operator-(const float radius) const +{ + FVector3 vmin = min; + FVector3 vmax = max; + + vmin.X += radius; + vmin.Y += radius; + vmin.Z += radius; + + vmax.X -= radius; + vmax.Y -= radius; + vmax.Z -= radius; + + return BBox(vmin, vmax); +} + +BBox BBox::operator-(const FVector3 &vec) const +{ + FVector3 vmin = min; + FVector3 vmax = max; + + vmin.X -= vec.X; + vmin.Y -= vec.Y; + vmin.Z -= vec.Z; + + vmax.X -= vec.X; + vmax.Y -= vec.Y; + vmax.Z -= vec.Z; + + return BBox(vmin, vmax); +} + +BBox &BBox::operator-=(const float radius) +{ + min.X += radius; + min.Y += radius; + min.Z += radius; + max.X -= radius; + max.Y -= radius; + max.Z -= radius; + return *this; +} + +BBox BBox::operator*(const FVector3 &vec) const +{ + BBox box = *this; + + if (vec.X < 0) { box.min.X += (vec.X - 1); } + else { box.max.X += (vec.X + 1); } + if (vec.Y < 0) { box.min.Y += (vec.Y - 1); } + else { box.max.Y += (vec.Y + 1); } + if (vec.Z < 0) { box.min.Z += (vec.Z - 1); } + else { box.max.Z += (vec.Z + 1); } + + return box; +} + +BBox &BBox::operator*=(const FVector3 &vec) +{ + if (vec.X < 0) { min.X += (vec.X - 1); } + else { max.X += (vec.X + 1); } + if (vec.Y < 0) { min.Y += (vec.Y - 1); } + else { max.Y += (vec.Y + 1); } + if (vec.Z < 0) { min.Z += (vec.Z - 1); } + else { max.Z += (vec.Z + 1); } + + return *this; +} + +BBox &BBox::operator=(const BBox &bbox) +{ + min = bbox.min; + max = bbox.max; + + return *this; +} + +FVector3 BBox::operator[](int index) const +{ + assert(index >= 0 && index < 2); + return index == 0 ? min : max; +} + +FVector3 &BBox::operator[](int index) +{ + assert(index >= 0 && index < 2); + return index == 0 ? min : max; +} + +bool BBox::LineIntersect(const FVector3 &start, const FVector3 &end) +{ + float ld[3]; + FVector3 center = Center(); + FVector3 extents = max - center; + FVector3 lineDir = (end - start) * 0.5f; + FVector3 lineCenter = lineDir + start; + FVector3 dir = lineCenter - center; + + ld[0] = fabs(lineDir.X); + if (fabs(dir.X) > extents.X + ld[0]) { return false; } + ld[1] = fabs(lineDir.Y); + if (fabs(dir.Y) > extents.Y + ld[1]) { return false; } + ld[2] = fabs(lineDir.Z); + if (fabs(dir.Z) > extents.Z + ld[2]) { return false; } + + FVector3 crossprod = lineDir ^ dir; + + if (fabs(crossprod.X) > extents.Y * ld[2] + extents.Z * ld[1]) { return false; } + if (fabs(crossprod.Y) > extents.X * ld[2] + extents.Z * ld[0]) { return false; } + if (fabs(crossprod.Z) > extents.X * ld[1] + extents.Y * ld[0]) { return false; } + + return true; +} + +// Assumes points is an array of 24 +void BBox::ToPoints(float *points) const +{ + points[0 * 3 + 0] = max[0]; + points[0 * 3 + 1] = min[1]; + points[0 * 3 + 2] = min[2]; + points[1 * 3 + 0] = max[0]; + points[1 * 3 + 1] = min[1]; + points[1 * 3 + 2] = max[2]; + points[2 * 3 + 0] = min[0]; + points[2 * 3 + 1] = min[1]; + points[2 * 3 + 2] = max[2]; + points[3 * 3 + 0] = min[0]; + points[3 * 3 + 1] = min[1]; + points[3 * 3 + 2] = min[2]; + points[4 * 3 + 0] = max[0]; + points[4 * 3 + 1] = max[1]; + points[4 * 3 + 2] = min[2]; + points[5 * 3 + 0] = max[0]; + points[5 * 3 + 1] = max[1]; + points[5 * 3 + 2] = max[2]; + points[6 * 3 + 0] = min[0]; + points[6 * 3 + 1] = max[1]; + points[6 * 3 + 2] = max[2]; + points[7 * 3 + 0] = min[0]; + points[7 * 3 + 1] = max[1]; + points[7 * 3 + 2] = min[2]; +} + +// Assumes vectors is an array of 8 +void BBox::ToVectors(FVector3 *vectors) const +{ + vectors[0][0] = max[0]; + vectors[0][1] = min[1]; + vectors[0][2] = min[2]; + vectors[1][0] = max[0]; + vectors[1][1] = min[1]; + vectors[1][2] = max[2]; + vectors[2][0] = min[0]; + vectors[2][1] = min[1]; + vectors[2][2] = max[2]; + vectors[3][0] = min[0]; + vectors[3][1] = min[1]; + vectors[3][2] = min[2]; + vectors[4][0] = max[0]; + vectors[4][1] = max[1]; + vectors[4][2] = min[2]; + vectors[5][0] = max[0]; + vectors[5][1] = max[1]; + vectors[5][2] = max[2]; + vectors[6][0] = min[0]; + vectors[6][1] = max[1]; + vectors[6][2] = max[2]; + vectors[7][0] = min[0]; + vectors[7][1] = max[1]; + vectors[7][2] = min[2]; +} + +inline FVector3 BBox::Center() const +{ + return FVector3( + (max.X + min.X) * 0.5f, + (max.Y + min.Y) * 0.5f, + (max.Z + min.Z) * 0.5f); +} + +inline FVector3 BBox::Extents() const +{ + return FVector3( + (max.X - min.X) * 0.5f, + (max.Y - min.Y) * 0.5f, + (max.Z - min.Z) * 0.5f); +} diff --git a/src/common/utility/bounds.h b/src/common/utility/bounds.h new file mode 100644 index 0000000000..29a86ce795 --- /dev/null +++ b/src/common/utility/bounds.h @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// Note: this is from ZDRay +//----------------------------------------------------------------------------- +// +// Copyright (c) 2013-2014 Samuel Villarreal +// svkaiser@gmail.com +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// + +#pragma once + +#include "vectors.h" + +class BBox +{ +public: + BBox(); + BBox(const FVector3& vMin, const FVector3& vMax); + + void Clear(); + FVector3 Center() const; + FVector3 Extents() const; + float Radius() const; + void AddPoint(const FVector3& vec); + bool PointInside(const FVector3& vec) const; + bool IntersectingBox(const BBox& box) const; + bool IntersectingBox2D(const BBox& box) const; + float DistanceToPlane(Plane& plane); + bool LineIntersect(const FVector3& start, const FVector3& end); + void ToPoints(float* points) const; + void ToVectors(FVector3* vectors) const; + + BBox operator+(const float radius) const; + BBox& operator+=(const float radius); + BBox operator+(const FVector3& vec) const; + BBox operator-(const float radius) const; + BBox operator-(const FVector3& vec) const; + BBox& operator-=(const float radius); + BBox operator*(const FVector3& vec) const; + BBox& operator*=(const FVector3& vec); + BBox& operator=(const BBox& bbox); + FVector3 operator[](int index) const; + FVector3& operator[](int index); + + FVector3 min; + FVector3 max; +}; \ No newline at end of file