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
00047 Vector local( const Vector& v ) const
00048 {
00049
00050 Vector t= Normalize( Vector(a, b) );
00051 Vector n= Normalize( Cross(t, Vector(a, c)) );
00052 Vector b= Cross(t, n);
00053
00054
00055 return Vector( Dot(v, b), Dot(v, t), Dot(v, n) );
00056 }
00057
00058
00059 Vector world( const Vector& v ) const
00060 {
00061
00062 Vector t= Normalize( Vector(a, b) );
00063 Vector n= Normalize( Cross(t, Vector(a, c)) );
00064 Vector b= Cross(t, n);
00065
00066
00067 return v.x * b + v.y * t + v.z * n;
00068 }
00069
00070 BBox getBBox( ) const
00071 {
00072 BBox bbox;
00073 bbox.Union(a);
00074 bbox.Union(b);
00075 bbox.Union(c);
00076
00077 return bbox;
00078 }
00079
00080
00081 Triangle transform( const Transform& t )
00082 {
00083 return Triangle( t(a), t(b), t(c) );
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 bool Intersect( const Ray &ray, const float htmax,
00109 float &rt, float &ru, float&rv ) const
00110 {
00111
00112 Vector ac(a, c);
00113 const Vector pvec= Cross(ray.d, ac);
00114
00115
00116 Vector ab(a, b);
00117 const float det= Dot(ab, pvec);
00118 if (det > -EPSILON && det < EPSILON)
00119 return false;
00120
00121 const float inv_det= 1.0f / det;
00122
00123
00124 const Vector tvec(a, ray.o);
00125
00126
00127 const float u= Dot(tvec, pvec) * inv_det;
00128 if(u < 0.0f || u > 1.0f)
00129 return false;
00130
00131
00132 const Vector qvec= Cross(tvec, ab);
00133
00134
00135 const float v= Dot(ray.d, qvec) * inv_det;
00136 if(v < 0.0f || u + v > 1.0f)
00137 return false;
00138
00139
00140 rt= Dot(ac, qvec) * inv_det;
00141 ru= u;
00142 rv= v;
00143
00144
00145 return (rt < htmax && rt > ray.tmin);
00146 }
00147
00148
00149
00150 Point getUVPoint( const float u, const float v ) const
00151 {
00152 const float w= 1.f - u - v;
00153 return a * w + b * u + c * v;
00154 }
00155
00156
00157 float sampleUniform( Sampler& sampler, Point& p ) const
00158 {
00159 float s= sqrtf(sampler.uniformFloat());
00160 float t= sampler.uniformFloat();
00161 float u= 1.f - s;
00162 float v= (1.f - t) * s;
00163 float w= t * s;
00164
00165 p= Point(u * a + v * b + w * c);
00166 return 1.f / area;
00167 }
00168
00169
00170
00171 float pdfUniform( const Point& p ) const
00172 {
00173 return 1.f / area;
00174 }
00175 };
00176
00177 }
00178 #endif