DYT/Tool/OpenSceneGraph-3.6.5/include/Imath/ImathPlane.h
2024-12-25 07:49:36 +08:00

261 lines
7.0 KiB
C++

//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenEXR Project.
//
//
// A 3D plane class template
//
#ifndef INCLUDED_IMATHPLANE_H
#define INCLUDED_IMATHPLANE_H
#include "ImathExport.h"
#include "ImathNamespace.h"
#include "ImathLine.h"
#include "ImathVec.h"
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
///
/// The `Plane3` class represents a half space in 3D, so the normal
/// may point either towards or away from origin. The plane `P` can
/// be represented by Plane3 as either `p` or `-p` corresponding to
/// the two half-spaces on either side of the plane. Any function
/// which computes a distance will return either negative or positive
/// values for the distance indicating which half-space the point is
/// in. Note that reflection, and intersection functions will operate
/// as expected.
template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Plane3
{
public:
/// @{
/// @name Direct access to member fields
/// The normal to the plane
Vec3<T> normal;
/// The distance from the origin to the plane
T distance;
/// @}
/// @{
/// @name Constructors
/// Uninitialized by default
IMATH_HOSTDEVICE Plane3() IMATH_NOEXCEPT {}
/// Initialize with a normal and distance
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3 (const Vec3<T>& normal, T distance) IMATH_NOEXCEPT;
/// Initialize with a point and a normal
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3 (const Vec3<T>& point, const Vec3<T>& normal) IMATH_NOEXCEPT;
/// Initialize with three points
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3 (const Vec3<T>& point1,
const Vec3<T>& point2,
const Vec3<T>& point3) IMATH_NOEXCEPT;
/// @}
/// @{
/// @name Manipulation
/// Set via a given normal and distance
IMATH_HOSTDEVICE void set (const Vec3<T>& normal, T distance) IMATH_NOEXCEPT;
/// Set via a given point and normal
IMATH_HOSTDEVICE void set (const Vec3<T>& point, const Vec3<T>& normal) IMATH_NOEXCEPT;
/// Set via three points
IMATH_HOSTDEVICE void set (const Vec3<T>& point1, const Vec3<T>& point2, const Vec3<T>& point3) IMATH_NOEXCEPT;
/// @}
/// @{
/// @name Utility Methods
/// Determine if a line intersects the plane.
/// @param line The line
/// @param[out] intersection The point of intersection
/// @return True if the line intersects the plane.
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
intersect (const Line3<T>& line, Vec3<T>& intersection) const IMATH_NOEXCEPT;
/// Determine if a line intersects the plane.
/// @param line The line
/// @param[out] parameter The parametric value of the point of intersection
/// @return True if the line intersects the plane.
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersectT (const Line3<T>& line, T& parameter) const IMATH_NOEXCEPT;
/// Return the distance from a point to the plane.
IMATH_HOSTDEVICE constexpr T distanceTo (const Vec3<T>& point) const IMATH_NOEXCEPT;
/// Reflect the given point around the plane.
IMATH_HOSTDEVICE constexpr Vec3<T> reflectPoint (const Vec3<T>& point) const IMATH_NOEXCEPT;
/// Reflect the direction vector around the plane
IMATH_HOSTDEVICE constexpr Vec3<T> reflectVector (const Vec3<T>& vec) const IMATH_NOEXCEPT;
/// @}
};
/// Plane of type float
typedef Plane3<float> Plane3f;
/// Plane of type double
typedef Plane3<double> Plane3d;
//---------------
// Implementation
//---------------
template <class T>
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Plane3<T>::Plane3 (const Vec3<T>& p0, const Vec3<T>& p1, const Vec3<T>& p2) IMATH_NOEXCEPT
{
set (p0, p1, p2);
}
template <class T>
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Plane3<T>::Plane3 (const Vec3<T>& n, T d) IMATH_NOEXCEPT
{
set (n, d);
}
template <class T>
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Plane3<T>::Plane3 (const Vec3<T>& p, const Vec3<T>& n) IMATH_NOEXCEPT
{
set (p, n);
}
template <class T>
IMATH_HOSTDEVICE inline void
Plane3<T>::set (const Vec3<T>& point1, const Vec3<T>& point2, const Vec3<T>& point3) IMATH_NOEXCEPT
{
normal = (point2 - point1) % (point3 - point1);
normal.normalize();
distance = normal ^ point1;
}
template <class T>
IMATH_HOSTDEVICE inline void
Plane3<T>::set (const Vec3<T>& point, const Vec3<T>& n) IMATH_NOEXCEPT
{
normal = n;
normal.normalize();
distance = normal ^ point;
}
template <class T>
IMATH_HOSTDEVICE inline void
Plane3<T>::set (const Vec3<T>& n, T d) IMATH_NOEXCEPT
{
normal = n;
normal.normalize();
distance = d;
}
template <class T>
IMATH_HOSTDEVICE constexpr inline T
Plane3<T>::distanceTo (const Vec3<T>& point) const IMATH_NOEXCEPT
{
return (point ^ normal) - distance;
}
template <class T>
IMATH_HOSTDEVICE constexpr inline Vec3<T>
Plane3<T>::reflectPoint (const Vec3<T>& point) const IMATH_NOEXCEPT
{
return normal * distanceTo (point) * -2.0 + point;
}
template <class T>
IMATH_HOSTDEVICE constexpr inline Vec3<T>
Plane3<T>::reflectVector (const Vec3<T>& v) const IMATH_NOEXCEPT
{
return normal * (normal ^ v) * 2.0 - v;
}
template <class T>
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
Plane3<T>::intersect (const Line3<T>& line, Vec3<T>& point) const IMATH_NOEXCEPT
{
T d = normal ^ line.dir;
if (d == 0.0)
return false;
T t = -((normal ^ line.pos) - distance) / d;
point = line (t);
return true;
}
template <class T>
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
Plane3<T>::intersectT (const Line3<T>& line, T& t) const IMATH_NOEXCEPT
{
T d = normal ^ line.dir;
if (d == 0.0)
return false;
t = -((normal ^ line.pos) - distance) / d;
return true;
}
/// Stream output, as "(normal distance)"
template <class T>
std::ostream&
operator<< (std::ostream& o, const Plane3<T>& plane)
{
return o << "(" << plane.normal << ", " << plane.distance << ")";
}
/// Transform a plane by a matrix
template <class T>
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3<T>
operator* (const Plane3<T>& plane, const Matrix44<T>& M) IMATH_NOEXCEPT
{
// T
// -1
// Could also compute M but that would suck.
//
Vec3<T> dir1 = Vec3<T> (1, 0, 0) % plane.normal;
T dir1Len = dir1 ^ dir1;
Vec3<T> tmp = Vec3<T> (0, 1, 0) % plane.normal;
T tmpLen = tmp ^ tmp;
if (tmpLen > dir1Len)
{
dir1 = tmp;
dir1Len = tmpLen;
}
tmp = Vec3<T> (0, 0, 1) % plane.normal;
tmpLen = tmp ^ tmp;
if (tmpLen > dir1Len)
{
dir1 = tmp;
}
Vec3<T> dir2 = dir1 % plane.normal;
Vec3<T> point = plane.distance * plane.normal;
return Plane3<T> (point * M, (point + dir2) * M, (point + dir1) * M);
}
/// Reflect the pla
template <class T>
IMATH_HOSTDEVICE constexpr inline Plane3<T>
operator- (const Plane3<T>& plane) IMATH_NOEXCEPT
{
return Plane3<T> (-plane.normal, -plane.distance);
}
IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
#endif // INCLUDED_IMATHPLANE_H