src/rcrt/primitives/Triangle.cpp

Go to the documentation of this file.
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         //calculation of vTangent
00048         
00049         Vec2D v1 = b->uv()-a->uv();
00050         Vec2D v2 = c->uv()-a->uv();
00051         
00052 //      std::cout << "v1: (" << v1[0] << "," << v1[1] << ")" << std::endl;
00053 //      std::cout << "v2: " << v2[0] << "," << v2[1] << ")"<< std::endl;
00054         
00055 //      float e = 1 / (v2.y()-(v2.x()/v1.x())*v1.y());
00056 //      float d = (-e*v2.x())/v1.x();
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 //      std::cout << "e: " << e << std::endl;
00062 //      std::cout << "d: " << e << std::endl;
00063         
00064         Vec3D edge1 = b->pos()-a->pos();
00065         Vec3D edge2 = c->pos()-a->pos();
00066         
00067 //      std::cout << "edge1: " << edge1 << std::endl;
00068 //      std::cout << "edge2: " << edge2 << std::endl;
00069         
00070         tangent = edge1 * d + edge2 * e;
00071 //      std::cout << "tangent: " << tangent << std::endl;
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 Intersection Triangle::intersect(Ray& ray) const
00106 {
00107         ray.tris++;
00108         const Point3D end = ray.org() + ray.dir();
00109         float V1 = volume(ray.org(), end, a->pos(), b->pos());
00110         //if(V1 == 0)
00111                 //std::cout << "[TRI-Intersect] V1 == 0" << std::endl;
00112         float V2 = volume(ray.org(), end, b->pos(), c->pos());
00113         //if(V2 == 0)
00114                 //std::cout << "[TRI-Intersect] V2 == 0" << std::endl;
00115         float V3 = volume(ray.org(), end, c->pos(), a->pos());
00116         //if(V3 == 0)
00117                 //std::cout << "[TRI-Intersect] V3 == 0" << std::endl;
00118                 
00119         if(!sameSign(V1,V2) || !sameSign(V2,V3) || !sameSign(V1,V3)){
00120                 std::cout << "[TRI-Intersect] V1 ="<< V1 << std::endl;
00121                 std::cout << "[TRI-Intersect] V2 ="<< V2 << std::endl;
00122                 std::cout << "[TRI-Intersect] V3 ="<< V3 << std::endl;
00123                 std::cout << "[TRI-Intersect] signs:"<<((V1 < 0) ? "-":"+") <<((V2 < 0) ? ",-":",+")<<((V3 < 0) ? ",-":",+") << std::endl;
00124                 float Va = volume(a->pos(), b->pos(), ray.org(), c->pos());
00125                 float V = V1+V2+V3;
00126                 float t = Va/V;
00127                 std::cout << "[TRI-Intersect] => no intersection dist="<<t << std::endl;
00128                 return Intersection();
00129         }
00130         float Va = volume(a->pos(), b->pos(), ray.org(), c->pos());
00131         float V = V1+V2+V3;
00132         float t = Va/V;
00133         if(t < numeric_limits<float>::epsilon()){
00134                 //std::cout << "[TRI-Intersect] t < "<< numeric_limits<float>::epsilon() << std::endl;
00135                 //std::cout << "[TRI-Intersect] => no intersection" << std::endl;
00136                 return Intersection();
00137         }
00138         //barycentric coords:
00139         float alpha = V2/V;
00140         float beta = V3/V;
00141         float gamma = 1-alpha-beta;
00142         
00143         bool flip = ray.dir()*faceNormal >= numeric_limits<float>::epsilon();
00144         //std::cout << "[TRI-Intersect] t = " << t << " backside=" << flip << " distToOrg=" << (ray.org()-getCentroid()).norm() << " angle="<<ray.dir()*normal << std::endl;
00145         
00146         Intersection is(t, this, ray.atDistance(t), beta, gamma, flip);
00147         
00148         Point2D uv(alpha * a->uv().x() + beta * b->uv().x() + gamma * c->uv().x(),
00149                         alpha * a->uv().y() + beta * b->uv().y() + gamma * c->uv().y());
00150         
00151         is.setUV(uv);
00152         
00153         return is;
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     //Vec3D normal = lambda * b->normal() + mue * c->normal() + (1-lambda-mue) * a->normal();
00186     //normal.normalize();
00187     bool flip = ray.dir()*faceNormal >= numeric_limits<float>::epsilon();
00188     //std::cout << "[TRI-Intersect] t = " << f << " backside=" << flip << " distToOrg=" << (ray.org()-getCentroid()).norm() << " angle="<<ray.dir()*normal << std::endl;
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         //fixing triangles with zero extension box
00258         //the BIH doesn't seem to like them
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         // calculate new Bounds of the Triangle (left and right)
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 }

Generated on Thu Jan 31 19:26:19 2008 for RenderingCompetitionRayTracer by  doxygen 1.5.3