Planes are ax+by+cz=d
Planes are changed to ax+by+cz=d, so the plane with normal (0, 1, 0) and distance 1 is y=1. Operators == and !=. Former-commit-id: 5267a183a9e6fb490de099d536ea2f64558f674d
This commit is contained in:
parent
077584ec49
commit
f2b80bfe64
|
|
@ -0,0 +1,75 @@
|
|||
#include <Nazara/Math/Plane.hpp>
|
||||
#include <catch.hpp>
|
||||
|
||||
SCENARIO("Plane", "[MATH][PLANE]")
|
||||
{
|
||||
GIVEN("Two planes normal(1, 1, 1), distance 1")
|
||||
{
|
||||
NzPlanef firstPlane(NzVector3f::Unit().Normalize(), 1.f);
|
||||
NzPlanef secondPlane(NzPlaned(NzVector3d::Unit().Normalize(), 1.0));
|
||||
|
||||
WHEN("We compare them")
|
||||
{
|
||||
THEN("They are equal")
|
||||
{
|
||||
REQUIRE(firstPlane == secondPlane);
|
||||
}
|
||||
|
||||
AND_THEN("We compare with normal(-1, -1, -1), distance -1")
|
||||
{
|
||||
REQUIRE(firstPlane == NzPlanef(-NzVector3f::Unit().Normalize(), -1.f));
|
||||
}
|
||||
|
||||
AND_THEN("They have the same distance from the same point")
|
||||
{
|
||||
NzVector3f point(-2.f, 3.f, 1.f);
|
||||
REQUIRE(firstPlane.Distance(point) == Approx(secondPlane.Distance(point)));
|
||||
REQUIRE(firstPlane.Distance(-2.f, 3.f, 1.f) == Approx(0.1547f));
|
||||
}
|
||||
|
||||
AND_THEN("Distance between Plane (0, 1, 0), distance 1 and point (0, 2, 0) should be 1")
|
||||
{
|
||||
REQUIRE(NzPlanef(NzVector3f::UnitY(), 1.f).Distance(NzVector3f::UnitY() * 2.f) == Approx(1.f));
|
||||
}
|
||||
|
||||
AND_THEN("Distance between Plane (0, 1, 0), distance 5 and point (0, 2, 0) should be -3")
|
||||
{
|
||||
REQUIRE(NzPlanef(NzVector3f::UnitY(), 5.f).Distance(NzVector3f::UnitY() * 2.f) == Approx(-3.f));
|
||||
}
|
||||
|
||||
AND_THEN("Distance between Plane (0, 1, 0), distance 1000 and point (0, 500, 0) and (0, 1500, 0)")
|
||||
{
|
||||
REQUIRE(NzPlanef(NzVector3f::UnitY(), 1000.f).Distance(NzVector3f::UnitY() * 500.f) == Approx(-500.f));
|
||||
REQUIRE(NzPlanef(NzVector3f::UnitY(), 1000.f).Distance(NzVector3f::UnitY() * 1500.f) == Approx(500.f));
|
||||
}
|
||||
|
||||
AND_THEN("Distance between Plane (0, -1, 0), distance -1000 and point (0, 500, 0) and (0, 1500, 0)")
|
||||
{
|
||||
REQUIRE(NzPlanef(-NzVector3f::UnitY(), -1000.f).Distance(NzVector3f::UnitY() * 500.f) == Approx(500.f));
|
||||
REQUIRE(NzPlanef(-NzVector3f::UnitY(), -1000.f).Distance(NzVector3f::UnitY() * 1500.f) == Approx(-500.f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIVEN("The plane XZ, distance 1 with 3 points (0, 1, 0), (1, 1, 1), (-1, 1, 0)")
|
||||
{
|
||||
WHEN("We do a positive plane")
|
||||
{
|
||||
NzPlanef xy(NzVector3f(2.f, 1.f, 0.f), NzVector3f(-1.f, 1.f, -1.f), NzVector3f(-1.f, 1.f, 0.f));
|
||||
|
||||
THEN("It must be equal to XZ distance 1")
|
||||
{
|
||||
REQUIRE(xy == NzPlanef(NzVector3f::UnitY(), 1.f));
|
||||
}
|
||||
}
|
||||
|
||||
WHEN("We do a negative plane")
|
||||
{
|
||||
NzPlanef xy(NzVector3f(0.f, 1.f, 0.f), NzVector3f(1.f, 1.f, 1.f), NzVector3f(-1.f, 1.f, 0.f));
|
||||
THEN("It must be equal to XZ distance 1")
|
||||
{
|
||||
REQUIRE(xy == NzPlanef(-NzVector3f::UnitY(), -1.f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (C) 2015 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_PLANE_HPP
|
||||
#define NAZARA_PLANE_HPP
|
||||
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
|
||||
template<typename T>
|
||||
class NzPlane
|
||||
{
|
||||
public:
|
||||
NzPlane() = default;
|
||||
NzPlane(T normalX, T normalY, T normalZ, T Distance);
|
||||
NzPlane(const T plane[4]);
|
||||
NzPlane(const NzVector3<T>& Normal, T Distance);
|
||||
NzPlane(const NzVector3<T>& Normal, const NzVector3<T>& point);
|
||||
NzPlane(const NzVector3<T>& point1, const NzVector3<T>& point2, const NzVector3<T>& point3);
|
||||
template<typename U> explicit NzPlane(const NzPlane<U>& plane);
|
||||
NzPlane(const NzPlane& plane) = default;
|
||||
~NzPlane() = default;
|
||||
|
||||
T Distance(const NzVector3<T>& point) const;
|
||||
T Distance(T x, T y, T z) const;
|
||||
|
||||
NzPlane& Set(T normalX, T normalY, T normalZ, T Distance);
|
||||
NzPlane& Set(const T plane[4]);
|
||||
NzPlane& Set(const NzPlane& plane);
|
||||
NzPlane& Set(const NzVector3<T>& Normal, T Distance);
|
||||
NzPlane& Set(const NzVector3<T>& Normal, const NzVector3<T>& point);
|
||||
NzPlane& Set(const NzVector3<T>& point1, const NzVector3<T>& point2, const NzVector3<T>& point3);
|
||||
template<typename U> NzPlane& Set(const NzPlane<U>& plane);
|
||||
|
||||
NzString ToString() const;
|
||||
|
||||
bool operator==(const NzPlane& plane) const;
|
||||
bool operator!=(const NzPlane& plane) const;
|
||||
|
||||
static NzPlane Lerp(const NzPlane& from, const NzPlane& to, T interpolation);
|
||||
static NzPlane XY();
|
||||
static NzPlane XZ();
|
||||
static NzPlane YZ();
|
||||
|
||||
NzVector3<T> normal;
|
||||
T distance;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzPlane<T>& plane);
|
||||
|
||||
typedef NzPlane<double> NzPlaned;
|
||||
typedef NzPlane<float> NzPlanef;
|
||||
|
||||
#include <Nazara/Math/Plane.inl>
|
||||
|
||||
#endif // NAZARA_PLANE_HPP
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
// Copyright (C) 2015 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 <Nazara/Core/StringStream.hpp>
|
||||
#include <Nazara/Math/Algorithm.hpp>
|
||||
#include <cstring>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
#define F(a) static_cast<T>(a)
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>::NzPlane(T normalX, T normalY, T normalZ, T D)
|
||||
{
|
||||
Set(normalX, normalY, normalZ, D);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>::NzPlane(const T plane[4])
|
||||
{
|
||||
Set(plane);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>::NzPlane(const NzVector3<T>& Normal, T D)
|
||||
{
|
||||
Set(Normal, D);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>::NzPlane(const NzVector3<T>& Normal, const NzVector3<T>& point)
|
||||
{
|
||||
Set(Normal, point);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>::NzPlane(const NzVector3<T>& point1, const NzVector3<T>& point2, const NzVector3<T>& point3)
|
||||
{
|
||||
Set(point1, point2, point3);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzPlane<T>::NzPlane(const NzPlane<U>& plane)
|
||||
{
|
||||
Set(plane);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzPlane<T>::Distance(const NzVector3<T>& point) const
|
||||
{
|
||||
return normal.DotProduct(point) - distance; // ax + by + cd - d = 0.
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T NzPlane<T>::Distance(T x, T y, T z) const
|
||||
{
|
||||
return Distance(NzVector3<T>(x, y, z));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(T normalX, T normalY, T normalZ, T D)
|
||||
{
|
||||
distance = D;
|
||||
normal.Set(normalX, normalY, normalZ);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(const T plane[4])
|
||||
{
|
||||
normal.Set(plane[0], plane[1], plane[2]);
|
||||
distance = plane[3];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(const NzPlane& plane)
|
||||
{
|
||||
std::memcpy(this, &plane, sizeof(NzPlane));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(const NzVector3<T>& Normal, T D)
|
||||
{
|
||||
distance = D;
|
||||
normal = Normal;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(const NzVector3<T>& Normal, const NzVector3<T>& point)
|
||||
{
|
||||
normal = Normal;
|
||||
distance = -normal.DotProduct(point);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T>& NzPlane<T>::Set(const NzVector3<T>& point1, const NzVector3<T>& point2, const NzVector3<T>& point3)
|
||||
{
|
||||
NzVector3<T> edge1 = point2 - point1;
|
||||
NzVector3<T> edge2 = point3 - point1;
|
||||
normal = edge1.CrossProduct(edge2);
|
||||
normal.Normalize();
|
||||
|
||||
distance = normal.DotProduct(point3);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
NzPlane<T>& NzPlane<T>::Set(const NzPlane<U>& plane)
|
||||
{
|
||||
normal.Set(plane.normal);
|
||||
distance = F(plane.distance);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzString NzPlane<T>::ToString() const
|
||||
{
|
||||
NzStringStream ss;
|
||||
|
||||
return ss << "Plane(Normal: " << normal.ToString() << "; Distance: " << distance << ')';
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzPlane<T>::operator==(const NzPlane& plane) const
|
||||
{
|
||||
return (normal == plane.normal && NzNumberEquals(distance, plane.distance)) || (normal == -plane.normal && NzNumberEquals(distance, -plane.distance));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool NzPlane<T>::operator!=(const NzPlane& plane) const
|
||||
{
|
||||
return !operator==(plane);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T> NzPlane<T>::Lerp(const NzPlane& from, const NzPlane& 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 NzPlane();
|
||||
}
|
||||
#endif
|
||||
|
||||
NzPlane plane;
|
||||
plane.distance = NzLerp(from.distance, to.distance, interpolation);
|
||||
plane.normal = NzVector3<T>::Lerp(from.normal, to.normal, interpolation);
|
||||
plane.normal.Normalize();
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T> NzPlane<T>::XY()
|
||||
{
|
||||
return NzPlane<T>(F(0.0), F(0.0), F(1.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T> NzPlane<T>::XZ()
|
||||
{
|
||||
return NzPlane<T>(F(0.0), F(1.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
NzPlane<T> NzPlane<T>::YZ()
|
||||
{
|
||||
return NzPlane<T>(F(1.0), F(0.0), F(0.0), F(0.0));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const NzPlane<T>& plane)
|
||||
{
|
||||
return out << plane.ToString();
|
||||
}
|
||||
|
||||
#undef F
|
||||
|
||||
#include <Nazara/Core/DebugOff.hpp>
|
||||
Loading…
Reference in New Issue