/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ #ifndef SE_INCL_PLANE_H #define SE_INCL_PLANE_H #ifdef PRAGMA_ONCE #pragma once #endif #include /* * Template class for plane in space of arbitrary dimensions and arbitrary type of coordinates */ template class Plane : public Vector { // normal vector public: Type pl_distance; // distance from point 0 along the normal vector public: /* Default constructor. */ inline Plane(void); /* Constructor from normal vector and distance. */ inline Plane(const Vector &normal, const Type distance); /* Constructor from normal vector and a point on plane. */ inline Plane(const Vector &normal, const Vector &point); /* Constructor from 3 points on plane, counter clockwise order. */ inline Plane(const Vector &point0, const Vector &point1, const Vector &point2); /* Reference distance. */ inline Type &Distance(void); inline const Type &Distance(void) const; /* Get a reference point on the plane. */ inline Vector ReferencePoint(void) const; /* Get a reference point on the plane, if origin is at given vector. */ inline Vector ReferencePoint(const Vector &vOrigin) const; /* Get distance of point from plane. */ inline const Type PointDistance(const Vector &point) const; /* Get missing coordinate value */ inline void GetCoordinate(const int iIndex, Vector &point) const; /* Get distance of plane from plane. */ inline const Type PlaneDistance(const Plane &plOther) const; /* Project a point to the plane. */ inline Vector ProjectPoint(const Vector &point) const; /* Project a direction vector to the plane. */ inline Vector ProjectDirection(const Vector &direction) const; /* Get index of the greatest coordinate of normal. */ inline INDEX GetMaxNormal(void) const; /* Deproject a point to the plane. */ inline Vector DeprojectPoint(const Plane &plOther, const Vector &point) const; /* Deproject a direction vector to the plane. */ inline Vector DeprojectDirection(const Plane &plOther, const Vector &point) const; /* Offset the plane forward for a given distance. */ inline void Offset(const Type offset); /* Mathematical operators. */ // unary minus (fliping of the plane) inline Plane operator-(void) const; // addition of vector (translation of the plane by the vector) inline Plane operator+(const Vector &vector2) const; inline Plane &operator+=(const Vector &vector2); inline Plane operator-(const Vector &vector2) const; inline Plane &operator-=(const Vector &vector2); // multiplication by a square matrix (sides swapped -- see implementation for notes) inline Plane &operator*=(const Matrix &matrix2); Plane operator*(const Matrix &matrix2) const; }; // inline functions implementation /* * Default constructor. */ template inline Plane::Plane(void) {} /* * Constructor from normal vector and distance. */ template inline Plane::Plane(const Vector &normal, const Type distance) : Vector(normal), pl_distance(distance) { // normalize normal vector ((Vector)*this).Normalize(); } /* * Constructor from normal vector and a point on plane. */ template inline Plane::Plane(const Vector &normal, const Vector &point) : Vector(normal) { // normalize normal vector Normalize(); pl_distance = (*this)%point; // distance = normalized_normal * point (dot product) } /* * Constructor from 3 points on plane, counter clockwise order. */ template inline Plane::Plane(const Vector &point0, const Vector &point1, const Vector &point2) { // create normal vector of plane Vector normal = (point2-point1)*(point0-point1); // cross product // construct plane with normal and one point *this = Plane(normal, point0); } /* * Reference distance. */ template inline Type &Plane::Distance(void) { return pl_distance; } template inline const Type &Plane::Distance(void) const { return pl_distance; } /* * Get distance of point from plane. */ template inline const Type Plane::PointDistance(const Vector &point) const { /* Distance of the point from (0,0,0) along the normal vector of the plane * minus distance of the plane from (0,0,0) along the normal vector of the plane. */ return (*this)%point-pl_distance; } /* * Get missing coordinate */ template inline void Plane::GetCoordinate(const int iIndex, Vector &point) const { Type sum = pl_distance; for( INDEX i=1; i<=iDimensions; i++) { if( i != iIndex) sum -= (*this)(i) * point(i); } point( iIndex) = sum/(*this)( iIndex); } /* * Get distance of plane from plane. */ template inline const Type Plane::PlaneDistance(const Plane &plOther) const { /* Distance of the reference point of ther other plane */ return PointDistance(plOther.ReferencePoint()); } /* * Get a reference point on the plane. */ template inline Vector Plane::ReferencePoint(void) const { // let the reference point be from (0,0,0) along the normal vector return ((Vector)*this)*pl_distance; } /* * Get a reference point on the plane, if origin is at given vector. */ template inline Vector Plane::ReferencePoint(const Vector &vOrigin) const { // let the reference point be from the origin along the normal vector, // as far as the origin is away from the plane return vOrigin-((Vector)*this)*(PointDistance(vOrigin)); } /* * Project a point to the plane. */ template inline Vector Plane::ProjectPoint(const Vector &point) const { return ReferencePoint(point); } /* * Project a direction vector on the plane. */ template inline Vector Plane::ProjectDirection(const Vector &direction) const { // projected direction is vector between projected endpoint and projected origin return ProjectPoint(direction) - ReferencePoint(); } template /* Deproject a point to the plane. */ inline Vector Plane::DeprojectPoint(const Plane &plOther, const Vector &point) const { Vector &vNormal = (Vector &) *this; Vector &vNormalOther = (Vector &) plOther; return point - vNormalOther*( PointDistance(point)/(vNormal%vNormalOther) ); } template /* Deproject a direction vector to the plane. */ inline Vector Plane::DeprojectDirection(const Plane &plOther, const Vector &point) const { Vector &vNormal = (Vector &) *this; Vector &vNormalOther = (Vector &) plOther; return point - vNormalOther*( (point%vNormal)/(vNormal%vNormalOther) ); } /* * Get index of the greatest coordinate of normal. */ template inline INDEX Plane::GetMaxNormal(void) const { INDEX iMax = 1; Type tMax = Abs((*this)(1)); for(INDEX i=2; i<=iDimensions; i++) { if (Abs((*this)(i)) > tMax) { tMax = Abs((*this)(i)); iMax = i; } } return iMax; } /* Offset the plane forward for a given distance. */ template inline void Plane::Offset(const Type offset) { pl_distance+=offset; } // unary minus (fliping of the plane) template inline Plane Plane::operator-(void) const { return Plane(-(Vector)*this, -pl_distance); } // addition of vector (translation along the vector) template inline Plane &Plane::operator+=(const Vector &vector2) { /* Calculate the length of the projection of the translation vector on the normal vector of the plane and add it to the plane distance. */ pl_distance += (*static_cast *>(this))%vector2; return *this; } template inline Plane Plane::operator+(const Vector &vector2) const { return Plane(*this)+=vector2; } template inline Plane &Plane::operator-=(const Vector &vector2) { /* Calculate the length of the projection of the translation vector on the normal vector of the plane and add it to the plane distance. */ pl_distance -= (*static_cast *>(this))%vector2; return *this; } template inline Plane Plane::operator-(const Vector &vector2) const { return Plane(*this)-=vector2; } /* * Multiplication of a plane by a square matrix. */ // NOTE: The matrix should have been on the left side of the vector, but the template syntax // wouldn't allow that. template inline Plane &Plane::operator*=(const Matrix &matrix2) { (*static_cast *>(this))*=matrix2; return *this; } template inline Plane Plane::operator*(const Matrix &matrix2) const { return Plane(*this)*=matrix2; } // helper functions for converting between FLOAT and DOUBLE planes inline DOUBLEplane3D FLOATtoDOUBLE(const FLOATplane3D &plf) { return DOUBLEplane3D( FLOATtoDOUBLE((FLOAT3D&)plf), FLOATtoDOUBLE(plf.Distance()) ); } inline FLOATplane3D DOUBLEtoFLOAT(const DOUBLEplane3D &pld) { return FLOATplane3D( DOUBLEtoFLOAT((DOUBLE3D&)pld), DOUBLEtoFLOAT(pld.Distance()) ); } #endif /* include-once check. */