00001 #include "Triangle.h"
00002
00003 using namespace std;
00004
00005 namespace rcrt
00006 {
00007
00008
00009 float Triangle::volume(const Point3D& o, const Point3D& e,
00010 const Point3D& a, const Point3D& b) const
00011 {
00012 return (a-o).crossP((b-o)) * (e-o)/6;
00013 }
00014
00015
00016 bool Triangle::sameSign(const float& a, const float& b) const
00017 {
00018 return (a < 0 == b < 0) || a == 0 || b == 0;
00019 }
00020
00021 Triangle::Triangle(const Point3D& pa,const Point3D& pb,const Point3D& pc,
00022 const Vec3D& fNo, SolidObject* parent):Primitive(parent),
00023 a(0),b(0),c(0),center((pa+pb.getPosVec3D()+pc.getPosVec3D())/3.0f),
00024 faceNormal(fNo.normalized()),smooth(false)
00025 {
00026 a = new Vertex(pa,faceNormal);
00027 b = new Vertex(pb,faceNormal);
00028 c = new Vertex(pc,faceNormal);
00029 ownVertices = true;
00030 updateBox();
00031 }
00032
00033 Triangle::Triangle(Vertex* av,Vertex* bv,Vertex* cv, SolidObject* parent, bool smo):Primitive(parent),
00034 a(av),b(bv),c(cv), center((a->pos()+b->pos().getPosVec3D()+c->pos().getPosVec3D())/3.0f),
00035 faceNormal((a->normal()+b->normal()+c->normal())/3.0f),smooth(smo)
00036 {
00037 updateBox();
00038 faceNormal.normalize();
00039 Vec3D fNormal = (b->pos()-a->pos()).crossP(c->pos()-a->pos());
00040 fNormal.normalize();
00041 if(fNormal*faceNormal < 0)
00042 fNormal = fNormal * -1;
00043 faceNormal = fNormal;
00044 ownVertices = false;
00045
00046
00047
00048
00049 Vec2D v1 = b->uv()-a->uv();
00050 Vec2D v2 = c->uv()-a->uv();
00051
00052
00053
00054
00055
00056
00057 float x = v2.det(v1);
00058 float d = -(v2[0]*(a->uv()[1]-1)-v2[1]*a->uv()[0])/x;
00059 float e = (v1[0]*(a->uv()[1]-1)-v1[1]*a->uv()[0])/x;
00060
00061
00062
00063
00064 Vec3D edge1 = b->pos()-a->pos();
00065 Vec3D edge2 = c->pos()-a->pos();
00066
00067
00068
00069
00070 tangent = edge1 * d + edge2 * e;
00071
00072 }
00073
00074
00075 Triangle::~Triangle()
00076 {
00077 if(ownVertices){
00078 if(a) delete a;
00079 if(b) delete b;
00080 if(c) delete c;
00081 }
00082 }
00083
00084 Vertex* Triangle::operator[] (int i) const
00085 {
00086 switch(i){
00087 case 0: return a;
00088 case 1: return b;
00089 case 2: return c;
00090 default: throw exception();
00091 }
00092 }
00093
00094 Vertex*& Triangle::operator[] (int i)
00095 {
00096 switch(i){
00097 case 0: return a;
00098 case 1: return b;
00099 case 2: return c;
00100 default: throw exception();
00101 }
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 Intersection Triangle::intersect(Ray& ray) const
00157 {
00158 ray.tris++;
00159 const Vec3D edge1 = b->pos()-a->pos();
00160 const Vec3D edge2 = c->pos()-a->pos();
00161
00162 const Vec3D pvec = ray.dir().crossP(edge2);
00163
00164 const float det = edge1 * pvec;
00165 if (fabs(det) < numeric_limits<float>::epsilon()) return Intersection();
00166
00167 const float inv_det = 1.0f / det;
00168
00169 const Vec3D tvec = ray.org()-a->pos();
00170 float lambda = tvec * pvec;
00171 lambda *= inv_det;
00172
00173 if (lambda < 0.0f || lambda > 1.0f) return Intersection();
00174
00175 const Vec3D qvec = tvec.crossP(edge1);
00176 float mue = ray.dir() * qvec;
00177 mue *= inv_det;
00178
00179 if (mue < 0.0f || mue+lambda > 1.0f) return Intersection();
00180
00181 float f = edge2 * qvec;
00182 f = f * inv_det - numeric_limits<float>::epsilon();
00183 if (ray.maxDist() <= f || f < numeric_limits<float>::epsilon() ) return Intersection();
00184
00185
00186
00187 bool flip = ray.dir()*faceNormal >= numeric_limits<float>::epsilon();
00188
00189
00190 Intersection is = Intersection(f, this, ray.atDistance(f), lambda, mue, flip);
00191
00192 is.setUV(Point2D(lambda,mue));
00193
00194 return is;
00195 }
00196
00197 const AABB& Triangle::getBoundingBox() const
00198 {
00199 return box;
00200 }
00201
00202 const Point3D& Triangle::getCentroid() const
00203 {
00204 return center;
00205 }
00206
00207 Vec3D Triangle::getSNormal(float beta, float gamma) const
00208 {
00209 if(smooth)
00210 return (beta * b->normal() + gamma * c->normal() + (1-beta-gamma) * a->normal()).normalized();
00211 else
00212 return faceNormal;
00213 }
00214
00215 Vec3D Triangle::getGNormal(float beta, float gamma) const
00216 {
00217 return faceNormal;
00218 }
00219
00220 Point2D Triangle::getUV(float beta, float gamma) const
00221 {
00222 float alpha = 1-beta-gamma;
00223 return Point2D(alpha * a->uv().x() + beta * b->uv().x() + gamma * c->uv().x(),
00224 alpha * a->uv().y() + beta * b->uv().y() + gamma * c->uv().y());
00225 }
00226
00227 Point3D Triangle::getPoint(float beta, float gamma) const
00228 {
00229 float alpha = 1-beta-gamma;
00230 return (c->pos()*gamma)+((a->pos()*alpha) + (b->pos()*beta));
00231 }
00232
00233 Point2D Triangle::getUV(const Point2D& p) const
00234 {
00235 float beta = p[0];
00236 float gamma = p[1];
00237 return getUV(beta,gamma);
00238 }
00239
00240 Point3D Triangle::getPoint(const Point2D& p) const
00241 {
00242 float beta = p[0];
00243 float gamma = p[1];
00244 return getPoint(beta,gamma);
00245 }
00246
00247 Vec3D Triangle::getTangent(float beta, float gamma) const
00248 {
00249 return tangent;
00250 }
00251
00252 void Triangle::updateBox()
00253 {
00254 Point3D maxp = Point3D(max(a->pos().x(),max(b->pos().x(),c->pos().x())),
00255 max(a->pos().y(),max(b->pos().y(),c->pos().y())),
00256 max(a->pos().z(),max(b->pos().z(),c->pos().z())));
00257
00258
00259 maxp[0] += 0.001;
00260 maxp[1] += 0.001;
00261 maxp[2] += 0.001;
00262 Point3D minp = Point3D(
00263 min(a->pos().x(),min(b->pos().x(),c->pos().x())),
00264 min(a->pos().y(),min(b->pos().y(),c->pos().y())),
00265 min(a->pos().z(),min(b->pos().z(),c->pos().z())));
00266 minp[0] -= 0.001;
00267 minp[1] -= 0.001;
00268 minp[2] -= 0.001;
00269 box.extend(maxp);
00270 box.extend(minp);
00271
00272 }
00273
00274 bool Triangle::isSmooth() const
00275 {
00276 return smooth;
00277 }
00278
00279 void Triangle::clipPlane(Axis axis, float plane, AABB& lBox, AABB& rBox) const {
00280 int max=0;
00281 Vec3D rays[2][2];
00282 Point3D p0(0);
00283
00284 if (a->pos()[axis] <= plane){
00285 lBox.extend(a->pos());
00286 if (b->pos()[axis] > plane){
00287 rays[max][0] = a->pos()-p0;
00288 rays[max++][1]= b->pos()-a->pos();
00289 }
00290 if (c->pos()[axis] > plane){
00291 rays[max][0]=a->pos()-p0;
00292 rays[max++][1]=c->pos()-a->pos();
00293 }
00294 }
00295 else
00296 rBox.extend(a->pos());
00297
00298 if (b->pos()[axis] <= plane){
00299 lBox.extend(b->pos());
00300 if (a->pos()[axis] > plane){
00301 rays[max][0]=b->pos()-p0;
00302 rays[max++][1]=a->pos()-b->pos();
00303 }
00304 if (c->pos()[axis] > plane){
00305 rays[max][0]=b->pos()-p0;
00306 rays[max++][1]=c->pos()-b->pos();
00307 }
00308 }
00309 else
00310 rBox.extend(b->pos());
00311
00312 if (c->pos()[axis] <= plane){
00313 lBox.extend(c->pos());
00314 if (a->pos()[axis] > plane){
00315 rays[max][0]=c->pos()-p0;
00316 rays[max++][1]=a->pos()-c->pos();
00317 }
00318 if (b->pos()[axis] > plane){
00319 rays[max][0]=c->pos()-p0;
00320 rays[max++][1]=b->pos()-c->pos();
00321 }
00322 }
00323 else
00324 rBox.extend(c->pos());
00325
00326
00327 Point3D point;
00328 for (int i=0; i<max; i++)
00329 {
00330 (rays[i][1]).normalize();
00331 float t=(plane - rays[i][0][axis])/rays[i][1][axis];
00332
00333 point=Point3D(rays[i][0]+t*rays[i][1]);
00334 lBox.extend(point);
00335 rBox.extend(point);
00336 }
00337 }
00338
00339 }