tge/engine/math/mPlane.h
2017-04-17 06:17:10 -06:00

285 lines
7.1 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _MPLANE_H_
#define _MPLANE_H_
#ifndef _MMATHFN_H_
#include "math/mMathFn.h"
#endif
#ifndef _MPOINT_H_
#include "math/mPoint.h"
#endif
//---------------------------------------------------------------------------
class PlaneF: public Point3F
{
public:
F32 d;
PlaneF();
PlaneF( const Point3F& p, const Point3F& n );
PlaneF( F32 _x, F32 _y, F32 _z, F32 _d);
PlaneF( const Point3F& j, const Point3F& k, const Point3F& l );
// Comparison operators
bool operator==(const PlaneF&a) const
{
return (a.x == x && a.y == y && a.z == z && a.d == d);
}
bool operator!=(const PlaneF&a) const
{
return (a.x != x || a.y != y || a.z != z || a.d == d);
}
// Methods
void set(const F32 _x, const F32 _y, const F32 _z);
void set( const Point3F& p, const Point3F& n);
void set( const Point3F& k, const Point3F& j, const Point3F& l );
void setPoint(const Point3F &p); // assumes the x,y,z fields are already set
// creates an un-normalized plane
void setXY(F32 zz);
void setYZ(F32 xx);
void setXZ(F32 yy);
void setXY(const Point3F& P, F32 dir);
void setYZ(const Point3F& P, F32 dir);
void setXZ(const Point3F& P, F32 dir);
void shiftX(F32 xx);
void shiftY(F32 yy);
void shiftZ(F32 zz);
void invert();
void neg();
Point3F project(Point3F pt); // project's the point onto the plane.
F32 distToPlane( const Point3F& cp ) const;
enum Side
{
Front = 1,
On = 0,
Back = -1
};
Side whichSide(const Point3F& cp) const;
F32 intersect(const Point3F &start, const Point3F &end) const;
bool isHorizontal() const;
bool isVertical() const;
Side whichSideBox(const Point3F& center,
const Point3F& axisx,
const Point3F& axisy,
const Point3F& axisz,
const Point3F& offset) const;
};
#define PARALLEL_PLANE 1e20f
#define PlaneSwitchCode(s, e) (s * 3 + e)
//---------------------------------------------------------------------------
inline PlaneF::PlaneF()
{
}
inline PlaneF::
PlaneF( F32 _x, F32 _y, F32 _z, F32 _d )
{
x = _x; y = _y; z = _z; d = _d;
}
inline PlaneF::PlaneF( const Point3F& p, const Point3F& n )
{
set(p,n);
}
inline PlaneF::PlaneF( const Point3F& j, const Point3F& k, const Point3F& l )
{
set(j,k,l);
}
inline void PlaneF::setXY( F32 zz )
{
x = y = 0.0f; z = 1.0f; d = -zz;
}
inline void PlaneF::setYZ( F32 xx )
{
x = 1.0f; z = y = 0.0f; d = -xx;
}
inline void PlaneF::setXZ( F32 yy )
{
x = z = 0.0f; y = 1.0f; d = -yy;
}
inline void PlaneF::setXY(const Point3F& point, F32 dir) // Normal = (0, 0, -1|1)
{
x = y = 0.0f;
d = -((z = dir) * point.z);
}
inline void PlaneF::setYZ(const Point3F& point, F32 dir) // Normal = (-1|1, 0, 0)
{
z = y = 0.0f;
d = -((x = dir) * point.x);
}
inline void PlaneF::setXZ(const Point3F& point, F32 dir) // Normal = (0, -1|1, 0)
{
x = z = 0.0f;
d = -((y = dir) * point.y);
}
inline void PlaneF::shiftX( F32 xx )
{
d -= xx * x;
}
inline void PlaneF::shiftY( F32 yy )
{
d -= yy * y;
}
inline void PlaneF::shiftZ( F32 zz )
{
d -= zz * z;
}
inline bool PlaneF::isHorizontal() const
{
return (x == 0.0f && y == 0.0f) ? true : false;
}
inline bool PlaneF::isVertical() const
{
return ((x != 0.0f || y != 0.0f) && z == 0.0f) ? true : false;
}
inline Point3F PlaneF::project(Point3F pt)
{
F32 dist = distToPlane(pt);
return Point3F(pt.x - x * dist, pt.y - y * dist, pt.z - z * dist);
}
inline F32 PlaneF::distToPlane( const Point3F& cp ) const
{
// return mDot(*this,cp) + d;
return (x * cp.x + y * cp.y + z * cp.z) + d;
}
inline PlaneF::Side PlaneF::whichSide(const Point3F& cp) const
{
F32 dist = distToPlane(cp);
if (dist >= 0.005f) // if (mFabs(dist) < 0.005f)
return Front; // return On;
else if (dist <= -0.005f) // else if (dist > 0.0f)
return Back; // return Front;
else // else
return On; // return Back;
}
inline void PlaneF::set(const F32 _x, const F32 _y, const F32 _z)
{
Point3F::set(_x,_y,_z);
}
//---------------------------------------------------------------------------
/// Calculate the coefficients of the plane passing through
/// a point with the given normal.
inline void PlaneF::setPoint(const Point3F &p)
{
d = -(p.x * x + p.y * y + p.z * z);
}
inline void PlaneF::set( const Point3F& p, const Point3F& n )
{
x = n.x; y = n.y; z = n.z;
normalize();
// Calculate the last plane coefficient.
d = -(p.x * x + p.y * y + p.z * z);
}
//---------------------------------------------------------------------------
/// Calculate the coefficients of the plane passing through
/// three points. Basically it calculates the normal to the three
/// points then calculates a plane through the middle point with that
/// normal.
inline void PlaneF::set( const Point3F& k, const Point3F& j, const Point3F& l )
{
// Point3F kj,lj,pv;
// kj = k;
// kj -= j;
// lj = l;
// lj -= j;
// mCross( kj, lj, &pv );
// set(j,pv);
// Above ends up making function calls up the %*#...
// This is called often enough to be a little more direct
// about it (sqrt should become intrinsic in the future)...
const F32 ax = k.x-j.x;
const F32 ay = k.y-j.y;
const F32 az = k.z-j.z;
const F32 bx = l.x-j.x;
const F32 by = l.y-j.y;
const F32 bz = l.z-j.z;
x = ay*bz - az*by;
y = az*bx - ax*bz;
z = ax*by - ay*bx;
m_point3F_normalize( (F32 *)(&x) );
d = -(j.x * x + j.y * y + j.z * z);
}
inline void PlaneF::invert()
{
x = -x;
y = -y;
z = -z;
d = -d;
}
inline void PlaneF::neg()
{
invert();
}
inline F32 PlaneF::intersect(const Point3F &p1, const Point3F &p2) const
{
const F32 den = mDot(p2 - p1, *this);
if(den == 0.0f)
return PARALLEL_PLANE;
return -distToPlane(p1) / den;
}
inline PlaneF::Side PlaneF::whichSideBox(const Point3F& center,
const Point3F& axisx,
const Point3F& axisy,
const Point3F& axisz,
const Point3F& /*offset*/) const
{
F32 baseDist = distToPlane(center);
F32 compDist = mFabs(mDot(axisx, *this)) +
mFabs(mDot(axisy, *this)) +
mFabs(mDot(axisz, *this));
if (baseDist >= compDist)
return Front;
else if (baseDist <= -compDist)
return Back;
else
return On;
}
#endif