www.pudn.com > simpleraytracer_v1_0.zip > plane.h
/*===================================================================
digital liberation front 2001
_______ ______ _______
/______/\ |______| /\______\
| \ \ | | / / |
| \| | | |/ |
|_____ \ | |_ / ______|
____| | | |_|| |_____
|____| |________||____|
Code by Nicholas Chapman[/ Ono-Sendai]
nickamy@paradise.net.nz
You may use this code for any non-commercial project,
as long as you do not remove this description.
You may not use this code for any commercial project.
====================================================================*/
#ifndef __PLANE_H__
#define __PLANE_H__
#include "vec3.h"
#include "mathstypes.h"
class CoordFrame;
class Plane
{
public:
inline Plane();
inline Plane(const Vec3&amt; origin, const Vec3&amt; normal);
inline Plane(const Vec3&amt; normal, float dist_from_origin);
inline Plane(const Plane&amt; rhs);
inline ~Plane();
// Plane&amt; operator = (const Plane&amt; rhs);
inline void set(const Vec3&amt; normal, float dist_from_origin);
inline void set(const Vec3&amt; origin, const Vec3&amt; normal);
inline void setUnnormalised(const Vec3&amt; origin, const Vec3&amt; nonunit_normal);
inline bool pointOnFrontSide(const Vec3&amt; point) const;
inline bool pointOnBackSide(const Vec3&amt; point) const;
inline bool isPointOnPlane(const Vec3&amt; point) const;
inline const Vec3 calcOrigin() const;//SLOW!
inline const Vec3 projOnPlane(const Vec3&amt; vec) const;
inline const Vec3 compNormalToPlane(const Vec3&amt; vec) const;
inline float signedDistToPoint(const Vec3&amt; p) const;
inline const Vec3 closestPointOnPlane(const Vec3&amt; p) const;
inline float getDist() const { return d; }
inline float getD() const { return d; }
inline const Vec3&amt; getNormal() const { return normal; }
//returns fraction of ray travelled. Will be in range [0, 1] if ray hit
inline float finiteRayIntersect(const Vec3&amt; raystart, const Vec3&amt; rayend) const;
inline float rayIntersect(const Vec3&amt; raystart, const Vec3 ray_unitdir) const;
const Plane transformToLocal(const CoordFrame&amt; coordframe) const;
inline bool isSpherePartiallyOnFrontSide(const Vec3&amt; sphere_center, float radius) const;
inline bool isSphereTotallyOnFrontSide(const Vec3&amt; sphere_center, float radius) const;
inline bool isPlaneOnFrontSide(const Plane&amt; p) const;
private:
float d;
Vec3 normal;
};
Plane::Plane()
{}
Plane::Plane(const Vec3&amt; origin, const Vec3&amt; normal_)
{
normal = normal_;
assert( epsEqual(normal.length(), 1.0f) );
d = dot(origin, normal);
}
Plane::Plane(const Vec3&amt; normal_, float dist_from_origin)
{
normal = normal_;
assert( epsEqual(normal.length(), 1.0f) );
d = dist_from_origin;
}
Plane::Plane(const Plane&amt; rhs)
{
normal = rhs.normal;
d = rhs.d;
}
Plane::~Plane()
{}
/*Plane&amt; Plane::operator = (const Plane&amt; rhs)
{
normal = rhs.normal;
d = rhs.d;
return *this;
}*/
void Plane::set(const Vec3&amt; normal_, float dist_from_origin)
{
normal = normal_;
assert( epsEqual(normal.length(), 1.0f) );
d = dist_from_origin;
}
void Plane::set(const Vec3&amt; origin, const Vec3&amt; normal_)
{
normal = normal_;
assert( epsEqual(normal.length(), 1.0f) );
d = dot(origin, normal);
}
void Plane::setUnnormalised(const Vec3&amt; origin, const Vec3&amt; nonunit_normal)
{
normal = nonunit_normal;
normal.normalise();
d = dot(origin, normal);
}
bool Plane::pointOnFrontSide(const Vec3&amt; point) const
{
return (dot(point, normal) >= d);
}
bool Plane::pointOnBackSide(const Vec3&amt; point) const
{
return (dot(point, normal) < d);
}
bool Plane::isPointOnPlane(const Vec3&amt; point) const
{
if(fabs(signedDistToPoint(point)) < 0.00001f)
return true;
else
return false;
}
const Vec3 Plane::calcOrigin() const
{
return normal * d;
}
const Vec3 Plane::projOnPlane(const Vec3&amt; vec) const
{
return vec - compNormalToPlane(vec);
}
const Vec3 Plane::compNormalToPlane(const Vec3&amt; vec) const
{
return dot(vec, normal) * normal;
}
float Plane::signedDistToPoint(const Vec3&amt; p) const
{
return dot(p, normal) - d;
}
const Vec3 Plane::closestPointOnPlane(const Vec3&amt; p) const
{
return p - (signedDistToPoint(p) * normal);
}
float Plane::finiteRayIntersect(const Vec3&amt; raystart, const Vec3&amt; rayend) const
{
const float raystart_dot_n = dot(raystart, normal);
const float rayend_dot_n = dot(rayend, normal);
const float denom = rayend_dot_n - raystart_dot_n;
if(denom == 0.0f)
return -1.0f;
return (d - raystart_dot_n) / denom;
}
float Plane::rayIntersect(const Vec3&amt; raystart, const Vec3 ray_unitdir) const
{
const float start_to_plane_dist = signedDistToPoint(raystart);
return start_to_plane_dist / -dot(ray_unitdir, normal);
//NOTE: deal with div by 0?
}
/*
const Plane Plane::transformToLocal(const CoordFrame&amt; coordframe) const
{
const Vec3 pointonplane = closestPointOnPlane(Vec3(0,0,0));
const Vec3&amt; transformed_point = coordframe.transformPointToLocal(pointonplane);
const Vec3&amt; transformed_normal = coordframe.transformVecToLocal(getNormal());
return Plane(transformed_point, transformed_normal);
//NOTE: check this is right
}*/
bool Plane::isSpherePartiallyOnFrontSide(const Vec3&amt; sphere_center, float radius) const
{
return signedDistToPoint(sphere_center) <= radius * -1.0f;
}
bool Plane::isSphereTotallyOnFrontSide(const Vec3&amt; sphere_center, float radius) const
{
return signedDistToPoint(sphere_center) >= radius;
}
bool Plane::isPlaneOnFrontSide(const Plane&amt; p) const
{
return epsEqual(p.getNormal(), this->getNormal())
&amt;&amt; p.getDist() > this->getDist();
}
#endif //__PLANE_H__