217 lines
4.4 KiB
C++
217 lines
4.4 KiB
C++
/*
|
||
* © Copyright 2014 – Urheberrechtshinweis
|
||
* Alle Rechte vorbehalten / All Rights Reserved
|
||
*
|
||
* Programmcode ist urheberrechtlich geschuetzt.
|
||
* Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner.
|
||
* Keine Verwendung ohne explizite Genehmigung.
|
||
* (vgl. § 106 ff UrhG / § 97 UrhG)
|
||
*/
|
||
|
||
#ifndef TRIANGLE3_H
|
||
#define TRIANGLE3_H
|
||
|
||
#include "Point3.h"
|
||
#include "Ray3.h"
|
||
|
||
struct Triangle3 {
|
||
|
||
Point3 p1;
|
||
Point3 p2;
|
||
Point3 p3;
|
||
|
||
public:
|
||
|
||
/** empty ctor */
|
||
Triangle3() : p1(), p2(), p3() {;}
|
||
|
||
/** ctor */
|
||
Triangle3(Point3 p1, Point3 p2, Point3 p3) : p1(p1), p2(p2), p3(p3) {;}
|
||
|
||
|
||
// Point3 cross(Point3 b, Point3 c) const {
|
||
// return Point3(
|
||
// b.y*c.z - c.y*b.z,
|
||
// b.z*c.x - c.z*b.x,
|
||
// b.x*c.y - c.x*b.y
|
||
// );
|
||
// }
|
||
|
||
// float dot(Point3 b, Point3 c) const {
|
||
// return b.x*c.x + b.y*c.y + b.z*c.z;
|
||
// }
|
||
|
||
Triangle3 operator - (const Point3 o) const {
|
||
return Triangle3(p1-o, p2-o, p3-o);
|
||
}
|
||
Triangle3& operator += (const Point3 o) {
|
||
p1 += o;
|
||
p2 += o;
|
||
p3 += o;
|
||
return *this;
|
||
}
|
||
Triangle3& operator -= (const Point3 o) {
|
||
p1 -= o;
|
||
p2 -= o;
|
||
p3 -= o;
|
||
return *this;
|
||
}
|
||
|
||
/** scale using 3 individual components */
|
||
Triangle3& operator *= (const Point3 o) {
|
||
p1 *= o;
|
||
p2 *= o;
|
||
p3 *= o;
|
||
return *this;
|
||
}
|
||
|
||
/** switch between CW<->CCW */
|
||
void reverse() {
|
||
std::swap(p2, p3);
|
||
}
|
||
|
||
void rotate_deg(const Point3 rot) {
|
||
p1 = p1.rot(rot.x/180.0f*M_PI, rot.y/180.0f*M_PI, rot.z/180.0f*M_PI);
|
||
p2 = p2.rot(rot.x/180.0f*M_PI, rot.y/180.0f*M_PI, rot.z/180.0f*M_PI);
|
||
p3 = p3.rot(rot.x/180.0f*M_PI, rot.y/180.0f*M_PI, rot.z/180.0f*M_PI);
|
||
}
|
||
|
||
// void ensureCCW() {
|
||
// Point3 norm = cross(p3-p1, p2-p1);
|
||
// if (norm.z < 0) {
|
||
// reverse();
|
||
// }
|
||
// }
|
||
|
||
Point3 getNormal() const {
|
||
return cross( p2-p1, p3-p1 ).normalized();
|
||
}
|
||
|
||
|
||
// http://www.lighthouse3d.com/tutorials/maths/ray-triangle-intersection/
|
||
bool intersects(const Ray3& ray, Point3& pos) const {
|
||
|
||
const Point3 e1 = p2-p1;
|
||
const Point3 e2 = p3-p1;
|
||
|
||
const Point3 h = cross(ray.dir, e2);
|
||
const double a = dot(e1, h);
|
||
|
||
if (a > -0.00001 && a < 0.00001) {return false;}
|
||
|
||
const double f = 1/a;
|
||
|
||
const Point3 s = ray.start - p1;
|
||
const double u = f * dot(s,h);
|
||
|
||
if (u < 0.0 || u > 1.0) {return false;}
|
||
|
||
const Point3 q = cross(s, e1);
|
||
const double v = f * dot(ray.dir, q);
|
||
|
||
if (v < 0.0 || u + v > 1.0) {return false;}
|
||
const double t = f * dot(e2,q);
|
||
|
||
|
||
if (t > 0.00001) {
|
||
pos = ray.start + (ray.dir * t);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
|
||
}
|
||
|
||
/** add some slight delta to prevent rounding issues */
|
||
bool intersectsDelta(const Ray3& ray, const double delta, Point3& pos) const {
|
||
|
||
const Point3 e1 = p2-p1;
|
||
const Point3 e2 = p3-p1;
|
||
|
||
// make delta an absolute value (independent of the triangle's size)
|
||
// larger triangle -> smaller delta, as u,v are [0:1]
|
||
//double deltaU = delta/e2.length();
|
||
//double deltaV = delta/e1.length();
|
||
|
||
const double deltaU = delta;
|
||
const double deltaV = delta;
|
||
|
||
const Point3 h = cross(ray.dir, e2);
|
||
const double a = dot(e1, h);
|
||
|
||
if (a > -0.00001 && a < 0.00001) {return false;}
|
||
|
||
const double f = 1/a;
|
||
|
||
const Point3 s = ray.start - p1;
|
||
const double u = f * dot(s,h);
|
||
|
||
if (u < 0.0-deltaU || u > 1.0+deltaU) {return false;}
|
||
|
||
const Point3 q = cross(s, e1);
|
||
const double v = f * dot(ray.dir, q);
|
||
|
||
if (v < 0.0-deltaV || u + v > 1.0+deltaV) {return false;}
|
||
const double t = f * dot(e2,q);
|
||
|
||
|
||
if (t > 0.00001) {
|
||
pos = ray.start + (ray.dir * t);
|
||
return true;
|
||
}
|
||
|
||
return true;
|
||
|
||
}
|
||
|
||
/** perform some sanity checks */
|
||
bool isValid() const {
|
||
if (p1 == p2) {return false;}
|
||
if (p1 == p3) {return false;}
|
||
if (p2 == p3) {return false;}
|
||
return true;
|
||
}
|
||
|
||
/*
|
||
int rayIntersectsTriangle(float *p, float *d,
|
||
float *v0, float *v1, float *v2) {
|
||
|
||
float e1[3],e2[3],h[3],s[3],q[3];
|
||
float a,f,u,v;
|
||
|
||
//crossProduct(h,d,e2);
|
||
a = innerProduct(e1,h);
|
||
|
||
if (a > -0.00001 && a < 0.00001)
|
||
return(false);
|
||
|
||
f = 1/a;
|
||
vector(s,p,v0);
|
||
u = f * (innerProduct(s,h));
|
||
|
||
if (u < 0.0 || u > 1.0)
|
||
return(false);
|
||
|
||
crossProduct(q,s,e1);
|
||
v = f * innerProduct(d,q);
|
||
|
||
if (v < 0.0 || u + v > 1.0)
|
||
return(false);
|
||
|
||
// at this stage we can compute t to find out where
|
||
// the intersection point is on the line
|
||
t = f * innerProduct(e2,q);
|
||
|
||
if (t > 0.00001) // ray intersection
|
||
return(true);
|
||
|
||
else // this means that there is a line intersection
|
||
// but not a ray intersection
|
||
return (false);
|
||
|
||
}
|
||
*/
|
||
};
|
||
|
||
#endif // TRIANGLE3_H
|