diff --git a/include/Nazara/Math/Sphere.hpp b/include/Nazara/Math/Sphere.hpp new file mode 100644 index 000000000..85a9ae8c7 --- /dev/null +++ b/include/Nazara/Math/Sphere.hpp @@ -0,0 +1,83 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine - Mathematics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_SPHERE_HPP +#define NAZARA_SPHERE_HPP + +#include +#include + +template +class NzSphere +{ + public: + NzSphere() = default; + NzSphere(T X, T Y, T Z, T Radius); + //NzSphere(const NzCircle& circle); + NzSphere(const NzVector3& pos, T Radius); + NzSphere(const T sphere[4]); + template explicit NzSphere(const NzSphere& sphere); + NzSphere(const NzSphere& sphere) = default; + ~NzSphere() = default; + + bool Contains(T X, T Y, T Z) const; + //bool Contains(const NzCube& cube) const; + bool Contains(const NzVector3& point) const; + + T Distance(T X, T Y, T Z) const; + T Distance(const NzVector3& point) const; + + NzSphere& ExtendTo(T X, T Y, T Z); + NzSphere& ExtendTo(const NzVector3& point); + + NzVector3 GetNegativeVertex(const NzVector3& normal) const; + NzVector3 GetPosition() const; + NzVector3 GetPositiveVertex(const NzVector3& normal) const; + + //bool Intersect(const NzCube& cube) const; + bool Intersect(const NzSphere& sphere) const; + + bool IsValid() const; + + NzSphere& MakeZero(); + + NzSphere& Set(T X, T Y, T Z, T Radius); + //NzSphere& Set(const NzCircle& rect); + NzSphere& Set(const NzSphere& sphere); + NzSphere& Set(const NzVector3& pos, T Radius); + NzSphere& Set(const T sphere[4]); + template NzSphere& Set(const NzSphere& sphere); + + T SquaredDistance(T X, T Y, T Z) const; + T SquaredDistance(const NzVector3& point) const; + + NzString ToString() const; + + T& operator[](unsigned int i); + T operator[](unsigned int i) const; + + NzSphere operator*(T scalar) const; + + NzSphere& operator*=(T scalar); + + bool operator==(const NzSphere& sphere) const; + bool operator!=(const NzSphere& sphere) const; + + static NzSphere Lerp(const NzSphere& from, const NzSphere& to, T interpolation); + static NzSphere Zero(); + + T x, y, z, radius; +}; + +template +std::ostream& operator<<(std::ostream& out, const NzSphere& sphere); + +typedef NzSphere NzSphered; +typedef NzSphere NzSpheref; + +#include + +#endif // NAZARA_SPHERE_HPP diff --git a/include/Nazara/Math/Sphere.inl b/include/Nazara/Math/Sphere.inl new file mode 100644 index 000000000..fb76ee95f --- /dev/null +++ b/include/Nazara/Math/Sphere.inl @@ -0,0 +1,326 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine - Mathematics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include + +#define F(a) static_cast(a) + +template +NzSphere::NzSphere(T X, T Y, T Z, T Radius) +{ + Set(X, Y, Z, Radius); +} +/* +template +NzSphere::NzSphere(const NzCircle& circle) +{ + Set(rect); +} +*/ +template +NzSphere::NzSphere(const NzVector3& pos, T Radius) +{ + Set(pos, Radius); +} + +template +NzSphere::NzSphere(const T sphere[6]) +{ + Set(sphere); +} + +template +template +NzSphere::NzSphere(const NzSphere& sphere) +{ + Set(sphere); +} + +template +bool NzSphere::Contains(T X, T Y, T Z) const +{ + return Distance(X, Y, Z) < F(0.0); +} +/* +template +bool NzSphere::Contains(const NzCube& point) const +{ +} +*/ +template +bool NzSphere::Contains(const NzVector3& point) const +{ + return Contains(point.x, point.y, point.z); +} + +template +T NzSphere::Distance(T X, T Y, T Z) const +{ + NzVector3 distance(X-x, Y-y, Z-z); + return distance.Length() - radius; +} + +template +T NzSphere::Distance(const NzVector3& point) const +{ + return Distance(point.x, point.y, point.z); +} + +template +NzSphere& NzSphere::ExtendTo(T X, T Y, T Z) +{ + T distance = Distance(X, Y, Z); + + if (distance > F(0.0)) + radius += distance; + + return *this; +} + +template +NzSphere& NzSphere::ExtendTo(const NzVector3& point) +{ + return ExtendTo(point); +} + +template +NzVector3 NzSphere::GetNegativeVertex(const NzVector3& normal) const +{ + NzVector3 neg(GetPosition()); + neg -= normal * radius; + + return neg; +} + +template +NzVector3 NzSphere::GetPosition() const +{ + return NzVector3(x, y, z); +} + +template +NzVector3 NzSphere::GetPositiveVertex(const NzVector3& normal) const +{ + NzVector3 pos(GetPosition()); + pos += normal * radius; + + return pos; +} +/* +template +bool NzSphere::Intersect(const NzCube& cube) const +{ + +} +*/ + +template +bool NzSphere::Intersect(const NzSphere& sphere) const +{ + return Distance(sphere.x, sphere.y, sphere.z) <= sphere.radius; +} + +template +bool NzSphere::IsValid() const +{ + return radius > F(0.0); +} + +template +NzSphere& NzSphere::MakeZero() +{ + x = F(0.0); + y = F(0.0); + z = F(0.0); + radius = F(0.0); + + return *this; +} + +template +NzSphere& NzSphere::Set(T X, T Y, T Z, T Radius) +{ + x = X; + y = Y; + z = Z; + radius = Radius; + + return *this; +} + +template +NzSphere& NzSphere::Set(const NzVector3& pos, T Radius) +{ + x = pos.x; + y = pos.y; + z = pos.z; + radius = Radius; + + return *this; +} +/* +template +NzSphere& NzCube::Set(const NzCircle& circle) +{ + x = circle.x; + y = circle.y; + z = F(0.0); + radius = circle.radius; + + return *this; +} +*/ +template +NzSphere& NzSphere::Set(const NzSphere& sphere) +{ + std::memcpy(this, &sphere, sizeof(NzSphere)); + + return *this; +} + +template +NzSphere& NzSphere::Set(const T sphere[4]) +{ + x = sphere[0]; + y = sphere[1]; + z = sphere[2]; + radius = sphere[3]; + + return *this; +} + +template +template +NzSphere& NzSphere::Set(const NzSphere& sphere) +{ + x = F(sphere.x); + y = F(sphere.y); + z = F(sphere.z); + radius = F(sphere.radius); + + return *this; +} + +template +T NzSphere::SquaredDistance(T X, T Y, T Z) const +{ + NzVector3 distance(X-x, Y-y, Z-z); + return radius*radius - distance.SquaredLength(); +} + +template +T NzSphere::SquaredDistance(const NzVector3& point) const +{ + return SquaredDistance(point.x, point.y, point.z); +} + +template +NzString NzSphere::ToString() const +{ + NzStringStream ss; + + return ss << "Sphere(" << x << ", " << y << ", " << z << "; " << radius << ')'; +} + +template +T& NzSphere::operator[](unsigned int i) +{ + #if NAZARA_MATH_SAFE + if (i >= 4) + { + NzStringStream ss; + ss << "Index out of range: (" << i << " >= 4)"; + + NazaraError(ss); + throw std::domain_error(ss.ToString()); + } + #endif + + return *(&x+i); +} + +template +T NzSphere::operator[](unsigned int i) const +{ + #if NAZARA_MATH_SAFE + if (i >= 4) + { + NzStringStream ss; + ss << "Index out of range: (" << i << " >= 4)"; + + NazaraError(ss); + throw std::domain_error(ss.ToString()); + } + #endif + + return *(&x+i); +} + +template +NzSphere NzSphere::operator*(T scalar) const +{ + return NzSphere(x, y, z, radius*scalar); +} + +template +NzSphere& NzSphere::operator*=(T scalar) +{ + radius *= scalar; +} + +template +bool NzSphere::operator==(const NzSphere& sphere) const +{ + return NzNumberEquals(x, sphere.x) && NzNumberEquals(y, sphere.y) && NzNumberEquals(z, sphere.z) && + NzNumberEquals(radius, sphere.radius); +} + +template +bool NzSphere::operator!=(const NzSphere& sphere) const +{ + return !operator==(sphere); +} + +template +NzSphere NzSphere::Lerp(const NzSphere& from, const NzSphere& to, T interpolation) +{ + #ifdef NAZARA_DEBUG + if (interpolation < F(0.0) || interpolation > F(1.0)) + { + NazaraError("Interpolation must be in range [0..1] (Got " + NzString::Number(interpolation) + ')'); + return Zero(); + } + #endif + + NzSphere sphere; + sphere.x = NzLerp(from.x, to.x, interpolation); + sphere.y = NzLerp(from.y, to.y, interpolation); + sphere.z = NzLerp(from.z, to.z, interpolation); + sphere.radius = NzLerp(from.radius, to.radius, interpolation); + + return sphere; +} + +template +NzSphere NzSphere::Zero() +{ + NzSphere sphere; + sphere.MakeZero(); + + return sphere; +} + +template +std::ostream& operator<<(std::ostream& out, const NzSphere& sphere) +{ + return out << sphere.ToString(); +} + +#undef F + +#include