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__