www.pudn.com > simpleraytracer_v1_0.zip > plane2.h


/*===================================================================


digital liberation front 2001

_______ ______ _______
/______/\ |______| /\______\
| \ \ | | / / |
| \| | | |/ |
|_____ \ | |_ / ______|
____| | | |_|| |_____
|____| |________||____|




Code by Nicholas Chapman
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 __PLANE2_H__
#define __PLANE2_H__


#include "vec2.h"
#include "mathstypes.h"
#include <assert.h>

class Plane2
{
public:
inline Plane2();
inline Plane2(const Vec2&amt; origin, const Vec2&amt; normal);
inline Plane2(const Vec2&amt; normal, float dist_from_origin);
inline Plane2(const Plane2&amt; rhs);
inline ~Plane2();

// Plane2&amt; operator = (const Plane2&amt; rhs);

inline void set(const Vec2&amt; normal, float dist_from_origin);
inline void set(const Vec2&amt; origin, const Vec2&amt; normal);

inline void setUnnormalised(const Vec2&amt; origin, const Vec2&amt; nonunit_normal);




inline bool pointOnFrontSide(const Vec2&amt; point) const;

inline bool pointOnBackSide(const Vec2&amt; point) const;

inline bool isPointOnPlane2(const Vec2&amt; point) const;

inline const Vec2 calcOrigin() const;//SLOW!

inline const Vec2 projOnPlane2(const Vec2&amt; vec) const;

inline const Vec2 compNormalToPlane2(const Vec2&amt; vec) const;

inline float signedDistToPoint(const Vec2&amt; p) const;

inline const Vec2 closestPointOnPlane2(const Vec2&amt; p) const;

inline float getDist() const { return d; }
inline float getD() const { return d; }

inline const Vec2&amt; getNormal() const { return normal; }

//returns fraction of ray travelled. Will be in range [0, 1] if ray hit
inline float rayIntersect(const Vec2&amt; raystart, const Vec2&amt; rayend) const;

//returns true if line segment intersected plane
inline bool getSegIntersectPos(const Vec2&amt; raystart, const Vec2&amt; rayend, Vec2&amt; in_pos_out) const;

//returns true if line clipped away completely
inline bool clipLineInPlane(Vec2&amt; start, Vec2&amt; end) const;


private:
float d;
Vec2 normal;
};


Plane2::Plane2()
{}

Plane2::Plane2(const Vec2&amt; origin, const Vec2&amt; normal_)
{
normal = normal_;

assert( epsEqual(normal.length(), 1) );

d = dot(origin, normal);
}

Plane2::Plane2(const Vec2&amt; normal_, float dist_from_origin)
{
normal = normal_;

assert( epsEqual(normal.length(), 1) );

d = dist_from_origin;
}

Plane2::Plane2(const Plane2&amt; rhs)
{
normal = rhs.normal;
d = rhs.d;
}

Plane2::~Plane2()
{}

/*Plane2&amt; Plane2::operator = (const Plane2&amt; rhs)
{
normal = rhs.normal;
d = rhs.d;

return *this;
}*/
void Plane2::set(const Vec2&amt; normal_, float dist_from_origin)
{
normal = normal_;

assert( epsEqual(normal.length(), 1) );

d = dist_from_origin;
}



void Plane2::set(const Vec2&amt; origin, const Vec2&amt; normal_)
{
normal = normal_;

assert( epsEqual(normal.length(), 1) );

d = dot(origin, normal);
}

void Plane2::setUnnormalised(const Vec2&amt; origin, const Vec2&amt; nonunit_normal)
{
normal = nonunit_normal;

normal.normalise();

d = dot(origin, normal);
}

bool Plane2::pointOnFrontSide(const Vec2&amt; point) const
{
return (dot(point, normal) >= d);
}

bool Plane2::pointOnBackSide(const Vec2&amt; point) const
{
return (dot(point, normal) < d);
}

bool Plane2::isPointOnPlane2(const Vec2&amt; point) const
{
if(fabs(signedDistToPoint(point)) < 0.00001)
return true;
else
return false;
}


const Vec2 Plane2::calcOrigin() const
{
return normal * d;
}

const Vec2 Plane2::projOnPlane2(const Vec2&amt; vec) const
{
return vec - compNormalToPlane2(vec);
}

const Vec2 Plane2::compNormalToPlane2(const Vec2&amt; vec) const
{
return normal * dot(vec, normal);
}

float Plane2::signedDistToPoint(const Vec2&amt; p) const
{
return dot(p, normal) - d;
}

const Vec2 Plane2::closestPointOnPlane2(const Vec2&amt; p) const
{
return p - (normal * signedDistToPoint(p));
}

float Plane2::rayIntersect(const Vec2&amt; raystart, const Vec2&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)
return -1;

return (d - raystart_dot_n) / denom;

}


bool Plane2::getSegIntersectPos(const Vec2&amt; raystart, const Vec2&amt; rayend, Vec2&amt; in_pos_out) const
{
const float fraction = rayIntersect(raystart, rayend);

if(fraction > 0 &amt;&amt; fraction < 1)
{
in_pos_out = rayend;
in_pos_out.sub(raystart);
in_pos_out *= fraction;

in_pos_out += raystart;
return true;
}

return false;
}






//returns true if line clipped away completely
bool Plane2::clipLineInPlane(Vec2&amt; start, Vec2&amt; end/*, bool&amt; waspartiallyclipped_out*/) const
{

if(pointOnFrontSide(start))
{
if(pointOnFrontSide(end))
{
//waspartiallyclipped_out = true;
return true;
}

//const float fraction_out = dot(start, normal) / (-dot(end, normal) + dot(start, normal));
//start += (end - start) * fraction_out;
start += (end-start) * rayIntersect(start, end);

//waspartiallyclipped_out = true;
return false;
}


if(pointOnFrontSide(end))
{
if(pointOnFrontSide(start))
{
//waspartiallyclipped_out = true;
return true;
}

// const float fraction_out = dot(end, normal) / (-dot(start, normal) + dot(end, normal));
// end += (start - end) * fraction_out;
end += (start - end) * rayIntersect(end, start);

//waspartiallyclipped_out = true;
return false;
}

//waspartiallyclipped_out = false;
return false;
}










#endif //__PLANE2_H__