00001
00002 #ifndef _GK_TRIANGLE_H
00003 #define _GK_TRIANGLE_H
00004
00005 #include "Geometry.h"
00006 #include "Transform.h"
00007 #include "Sampler.h"
00008
00009 namespace gk {
00010
00011
00012 struct Triangle
00013 {
00014 Point a, b, c;
00015 float area;
00016
00017
00018 Triangle( ) {}
00019
00020
00021 Triangle( const Point& a, const Point& b, const Point& c )
00022 :
00023 a(a), b(b), c(c),
00024 area(getArea())
00025 {}
00026
00027
00028 ~Triangle( ) {}
00029
00030 float getArea( ) const
00031 {
00032 Vector ab(a, b);
00033 Vector ac(a, c);
00034
00035 return .5f * Cross(ab, ac).Length();
00036 }
00037
00038 Normal getNormal( ) const
00039 {
00040 Vector ab(a, b);
00041 Vector ac(a, c);
00042
00043 return Normal( Normalize(Cross(ab, ac)) );
00044 }
00045
00046 BBox getBBox( ) const
00047 {
00048 BBox bbox;
00049 bbox.Union(a);
00050 bbox.Union(b);
00051 bbox.Union(c);
00052
00053 return bbox;
00054 }
00055
00056
00057 Triangle transform( const Transform& t )
00058 {
00059 return Triangle( t(a), t(b), t(c) );
00060 }
00061
00062
00063
00064
00065
00066
00067 bool Intersect( const Ray &ray, const float htmax,
00068 float &rt, float &ru, float&rv ) const
00069 {
00070
00071 Vector ac(a, c);
00072 const Vector pvec= Cross(ray.d, ac);
00073
00074
00075 Vector ab(a, b);
00076 const float det= Dot(ab, pvec);
00077 if (det > -EPSILON && det < EPSILON)
00078 return false;
00079
00080 const float inv_det= 1.0f / det;
00081
00082
00083 const Vector tvec(a, ray.o);
00084
00085
00086 const float u= Dot(tvec, pvec) * inv_det;
00087 if(u < 0.0f || u > 1.0f)
00088 return false;
00089
00090
00091 const Vector qvec= Cross(tvec, ab);
00092
00093
00094 const float v= Dot(ray.d, qvec) * inv_det;
00095 if(v < 0.0f || u + v > 1.0f)
00096 return false;
00097
00098
00099 rt= Dot(ac, qvec) * inv_det;
00100 ru= u;
00101 rv= v;
00102
00103
00104 return (rt < htmax && rt > ray.tmin);
00105 }
00106
00107
00108 Point getUVPoint( const float u, const float v ) const
00109 {
00110 const float w= 1.f - u - v;
00111 return a * w + b * u + c * v;
00112 }
00113
00114 float sampleUniform( Sampler& sampler, Point& p ) const
00115 {
00116 float s= sqrtf(sampler.uniformFloat());
00117 float t= sampler.uniformFloat();
00118 float u= 1.f - s;
00119 float v= (1.f - t) * s;
00120 float w= t * s;
00121
00122 p= Point(u * a + v * b + w * c);
00123 return 1.f / area;
00124 }
00125
00126 float pdfUniform( const Point& p ) const
00127 {
00128 return 1.f / area;
00129 }
00130 };
00131
00132 }
00133 #endif