2007-05-20 11:03:49 -07:00
|
|
|
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
|
|
|
// This file is part of the "Irrlicht Engine".
|
|
|
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
|
|
|
|
|
|
|
#ifndef __IRR_PLANE_3D_H_INCLUDED__
|
|
|
|
#define __IRR_PLANE_3D_H_INCLUDED__
|
|
|
|
|
|
|
|
#include "irrMath.h"
|
|
|
|
#include "vector3d.h"
|
|
|
|
|
|
|
|
namespace irr
|
|
|
|
{
|
|
|
|
namespace core
|
|
|
|
{
|
|
|
|
|
|
|
|
//! Enumeration for intersection relations of 3d objects
|
2007-05-26 17:04:58 -07:00
|
|
|
enum EIntersectionRelation3D
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
ISREL3D_FRONT = 0,
|
|
|
|
ISREL3D_BACK,
|
|
|
|
ISREL3D_PLANAR,
|
|
|
|
ISREL3D_SPANNING,
|
|
|
|
ISREL3D_CLIPPED
|
|
|
|
};
|
|
|
|
|
|
|
|
//! Template plane class with some intersection testing methods.
|
|
|
|
template <class T>
|
|
|
|
class plane3d
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
// Constructors
|
|
|
|
|
2007-07-30 04:01:04 -07:00
|
|
|
plane3d(): Normal(0,1,0) { recalculateD(vector3d<T>(0,0,0)); }
|
|
|
|
plane3d(const vector3d<T>& MPoint, const vector3d<T>& Normal) : Normal(Normal) { recalculateD(MPoint); }
|
|
|
|
plane3d(T px, T py, T pz, T nx, T ny, T nz) : Normal(nx, ny, nz) { recalculateD(vector3d<T>(px, py, pz)); }
|
|
|
|
plane3d(const vector3d<T>& point1, const vector3d<T>& point2, const vector3d<T>& point3) { setPlane(point1, point2, point3); }
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
// operators
|
|
|
|
|
2007-07-30 04:01:04 -07:00
|
|
|
inline bool operator==(const plane3d<T>& other) const { return (D==other.D && Normal==other.Normal);}
|
|
|
|
inline bool operator!=(const plane3d<T>& other) const { return !(D==other.D && Normal==other.Normal);}
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
// functions
|
|
|
|
|
|
|
|
void setPlane(const vector3d<T>& point, const vector3d<T>& nvector)
|
|
|
|
{
|
|
|
|
Normal = nvector;
|
|
|
|
recalculateD(point);
|
|
|
|
}
|
|
|
|
|
|
|
|
void setPlane(const vector3d<T>& nvect, T d)
|
|
|
|
{
|
|
|
|
Normal = nvect;
|
|
|
|
D = d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setPlane(const vector3d<T>& point1, const vector3d<T>& point2, const vector3d<T>& point3)
|
|
|
|
{
|
|
|
|
// creates the plane from 3 memberpoints
|
|
|
|
Normal = (point2 - point1).crossProduct(point3 - point1);
|
|
|
|
Normal.normalize();
|
|
|
|
|
|
|
|
recalculateD(point1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! Returns an intersection with a 3d line.
|
|
|
|
//! \param lineVect: Vector of the line to intersect with.
|
|
|
|
//! \param linePoint: Point of the line to intersect with.
|
|
|
|
//! \param outIntersection: Place to store the intersection point, if there is one.
|
|
|
|
//! \return Returns true if there was an intersection, false if there was not.
|
|
|
|
bool getIntersectionWithLine(const vector3d<T>& linePoint, const vector3d<T>& lineVect,
|
|
|
|
vector3d<T>& outIntersection) const
|
|
|
|
{
|
|
|
|
T t2 = Normal.dotProduct(lineVect);
|
|
|
|
|
|
|
|
if (t2 == 0)
|
|
|
|
return false;
|
|
|
|
|
2007-05-26 17:04:58 -07:00
|
|
|
T t =- (Normal.dotProduct(linePoint) + D) / t2;
|
2007-05-20 11:03:49 -07:00
|
|
|
outIntersection = linePoint + (lineVect * t);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Returns where on a line between two points an intersection with this plane happened.
|
|
|
|
//! Only useful if known that there is an intersection.
|
|
|
|
//! \param linePoint1: Point1 of the line to intersect with.
|
|
|
|
//! \param linePoint2: Point2 of the line to intersect with.
|
|
|
|
//! \return Returns where on a line between two points an intersection with this plane happened.
|
|
|
|
//! For example, 0.5 is returned if the intersection happened exectly in the middle of the two points.
|
|
|
|
f32 getKnownIntersectionWithLine(const vector3d<T>& linePoint1,
|
|
|
|
const vector3d<T>& linePoint2) const
|
|
|
|
{
|
|
|
|
vector3d<T> vect = linePoint2 - linePoint1;
|
|
|
|
T t2 = (f32)Normal.dotProduct(vect);
|
|
|
|
return (f32)-((Normal.dotProduct(linePoint1) + D) / t2);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Returns an intersection with a 3d line, limited between two 3d points.
|
|
|
|
//! \param linePoint1: Point 1 of the line.
|
|
|
|
//! \param linePoint2: Point 2 of the line.
|
|
|
|
//! \param outIntersection: Place to store the intersection point, if there is one.
|
|
|
|
//! \return Returns true if there was an intersection, false if there was not.
|
2007-05-26 17:04:58 -07:00
|
|
|
bool getIntersectionWithLimitedLine(const vector3d<T>& linePoint1,
|
2007-05-20 11:03:49 -07:00
|
|
|
const vector3d<T>& linePoint2, vector3d<T>& outIntersection) const
|
|
|
|
{
|
|
|
|
return ( getIntersectionWithLine(linePoint1, linePoint2 - linePoint1, outIntersection) &&
|
|
|
|
outIntersection.isBetweenPoints(linePoint1, linePoint2));
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Classifies the relation of a point to this plane.
|
|
|
|
//! \param point: Point to classify its relation.
|
|
|
|
//! \return Returns ISREL3D_FRONT if the point is in front of the plane,
|
|
|
|
//! ISREL3D_BACK if the point is behind of the plane, and
|
|
|
|
//! ISREL3D_PLANAR if the point is within the plane.
|
|
|
|
EIntersectionRelation3D classifyPointRelation(const vector3d<T>& point) const
|
|
|
|
{
|
|
|
|
const T d = Normal.dotProduct(point) + D;
|
|
|
|
|
|
|
|
if (d < -ROUNDING_ERROR_32)
|
2007-05-26 17:04:58 -07:00
|
|
|
return ISREL3D_BACK;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
if (d > ROUNDING_ERROR_32)
|
2007-05-26 17:04:58 -07:00
|
|
|
return ISREL3D_FRONT;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
return ISREL3D_PLANAR;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Recalculates the distance from origin by applying
|
|
|
|
//! a new member point to the plane.
|
|
|
|
void recalculateD(const vector3d<T>& MPoint)
|
|
|
|
{
|
|
|
|
D = - MPoint.dotProduct(Normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Returns a member point of the plane.
|
|
|
|
vector3d<T> getMemberPoint() const
|
|
|
|
{
|
|
|
|
return Normal * -D;
|
|
|
|
}
|
|
|
|
|
2007-05-26 17:04:58 -07:00
|
|
|
//! Tests if there is an intersection between with the other plane
|
2007-05-20 11:03:49 -07:00
|
|
|
//! \return Returns true if there is a intersection.
|
2007-05-26 17:04:58 -07:00
|
|
|
bool existsIntersection(const plane3d<T>& other) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
vector3d<T> cross = other.Normal.crossProduct(Normal);
|
|
|
|
return cross.getLength() > core::ROUNDING_ERROR_32;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Intersects this plane with another.
|
|
|
|
//! \return Returns true if there is a intersection, false if not.
|
|
|
|
bool getIntersectionWithPlane(const plane3d<T>& other, vector3d<T>& outLinePoint,
|
|
|
|
vector3d<T>& outLineVect) const
|
|
|
|
{
|
2007-05-26 17:04:58 -07:00
|
|
|
T fn00 = Normal.getLength();
|
|
|
|
T fn01 = Normal.dotProduct(other.Normal);
|
|
|
|
T fn11 = other.Normal.getLength();
|
2007-05-20 11:03:49 -07:00
|
|
|
f64 det = fn00*fn11 - fn01*fn01;
|
|
|
|
|
|
|
|
if (fabs(det) < ROUNDING_ERROR_64 )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
det = 1.0 / det;
|
|
|
|
f64 fc0 = (fn11*-D + fn01*other.D) * det;
|
|
|
|
f64 fc1 = (fn00*-other.D + fn01*D) * det;
|
|
|
|
|
|
|
|
outLineVect = Normal.crossProduct(other.Normal);
|
|
|
|
outLinePoint = Normal*(T)fc0 + other.Normal*(T)fc1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Returns the intersection point with two other planes if there is one.
|
2007-05-26 17:04:58 -07:00
|
|
|
bool getIntersectionWithPlanes(const plane3d<T>& o1,
|
2007-05-20 11:03:49 -07:00
|
|
|
const plane3d<T>& o2, vector3d<T>& outPoint) const
|
|
|
|
{
|
|
|
|
vector3d<T> linePoint, lineVect;
|
|
|
|
if (getIntersectionWithPlane(o1, linePoint, lineVect))
|
|
|
|
return o2.getIntersectionWithLine(linePoint, lineVect, outPoint);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-05-28 04:14:47 -07:00
|
|
|
//! Test if the triangle would be front or backfacing from any
|
|
|
|
//! point. Thus, this method assumes a camera position from
|
|
|
|
//! which the triangle is definitely visible when looking into
|
|
|
|
//! the given direction.
|
|
|
|
//! Note that this only works if the normal is Normalized.
|
|
|
|
//! Do not use this method with points as it will give wrong results!
|
2007-05-20 11:03:49 -07:00
|
|
|
//! \param lookDirection: Look direction.
|
2007-05-28 04:14:47 -07:00
|
|
|
//! \return Returns true if the plane is front facing and
|
|
|
|
//! false if it is backfacing.
|
2007-05-20 11:03:49 -07:00
|
|
|
bool isFrontFacing(const vector3d<T>& lookDirection) const
|
|
|
|
{
|
|
|
|
const f32 d = Normal.dotProduct(lookDirection);
|
|
|
|
return F32_LOWER_EQUAL_0 ( d );
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Returns the distance to a point. Note that this only
|
|
|
|
//! works if the normal is Normalized.
|
|
|
|
T getDistanceTo(const vector3d<T>& point) const
|
|
|
|
{
|
|
|
|
return point.dotProduct(Normal) + D;
|
|
|
|
}
|
2007-05-26 17:04:58 -07:00
|
|
|
|
2007-05-20 11:03:49 -07:00
|
|
|
// member variables
|
2007-05-26 17:04:58 -07:00
|
|
|
|
2007-05-20 11:03:49 -07:00
|
|
|
vector3d<T> Normal; // normal vector
|
2007-05-26 17:04:58 -07:00
|
|
|
T D; // distance from origin
|
2007-05-20 11:03:49 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//! Typedef for a f32 3d plane.
|
|
|
|
typedef plane3d<f32> plane3df;
|
|
|
|
//! Typedef for an integer 3d plane.
|
|
|
|
typedef plane3d<s32> plane3di;
|
|
|
|
|
|
|
|
} // end namespace core
|
|
|
|
} // end namespace irr
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|