00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef _LUXRAYS_TRIANGLE_H
00024 #define _LUXRAYS_TRIANGLE_H
00025
00026 #include "luxrays/luxrays.h"
00027
00028 namespace luxrays {
00029
00030 inline void UniformSampleTriangle(const float u0, const float u1, float *u, float *v) {
00031 float su1 = sqrtf(u0);
00032 *u = 1.f - su1;
00033 *v = u1 * su1;
00034 }
00035
00036 class Triangle {
00037 public:
00038 Triangle() { }
00039 Triangle(const unsigned int v0, const unsigned int v1, const unsigned int v2) {
00040 v[0] = v0;
00041 v[1] = v1;
00042 v[2] = v2;
00043 }
00044
00045 BBox WorldBound(const Point *verts) const {
00046 const Point &p0 = verts[v[0]];
00047 const Point &p1 = verts[v[1]];
00048 const Point &p2 = verts[v[2]];
00049
00050 return Union(BBox(p0, p1), p2);
00051 }
00052
00053 bool Intersect(const Ray &ray, const Point *verts, RayHit *triangleHit) const {
00054 const Point &p0 = verts[v[0]];
00055 const Point &p1 = verts[v[1]];
00056 const Point &p2 = verts[v[2]];
00057 const Vector e1 = p1 - p0;
00058 const Vector e2 = p2 - p0;
00059 const Vector s1 = Cross(ray.d, e2);
00060
00061 const float divisor = Dot(s1, e1);
00062 if (divisor == 0.f)
00063 return false;
00064
00065 const float invDivisor = 1.f / divisor;
00066
00067
00068 const Vector d = ray.o - p0;
00069 const float b1 = Dot(d, s1) * invDivisor;
00070 if (b1 < 0.f)
00071 return false;
00072
00073
00074 const Vector s2 = Cross(d, e1);
00075 const float b2 = Dot(ray.d, s2) * invDivisor;
00076 if (b2 < 0.f)
00077 return false;
00078
00079 const float b0 = 1.f - b1 - b2;
00080 if (b0 < 0.f)
00081 return false;
00082
00083
00084 const float t = Dot(e2, s2) * invDivisor;
00085 if (t < ray.mint || t > ray.maxt)
00086 return false;
00087
00088 triangleHit->t = t;
00089 triangleHit->b1 = b1;
00090 triangleHit->b2 = b2;
00091
00092 return true;
00093 }
00094
00095 float Area(const Point *verts) const {
00096 const Point &p0 = verts[v[0]];
00097 const Point &p1 = verts[v[1]];
00098 const Point &p2 = verts[v[2]];
00099
00100 return 0.5f * Cross(p1 - p0, p2 - p0).Length();
00101 }
00102
00103 void Sample(const Point *verts, const float u0,
00104 const float u1, Point *p, float *b0, float *b1, float *b2) const {
00105 UniformSampleTriangle(u0, u1, b0, b1);
00106
00107
00108 const Point &p0 = verts[v[0]];
00109 const Point &p1 = verts[v[1]];
00110 const Point &p2 = verts[v[2]];
00111 *b2 = 1.f - (*b0) - (*b1);
00112 *p = (*b0) * p0 + (*b1) * p1 + (*b2) * p2;
00113 }
00114
00115 static float Area(const Point &p0, const Point &p1, const Point &p2) {
00116 return 0.5f * Cross(p1 - p0, p2 - p0).Length();
00117 }
00118
00119 unsigned int v[3];
00120 };
00121
00122 inline std::ostream & operator<<(std::ostream &os, const Triangle &tri) {
00123 os << "Triangle[" << tri.v[0] << ", " << tri.v[1] << ", " << tri.v[2] << "]";
00124 return os;
00125 }
00126
00127 }
00128
00129 #endif