Cylinder.cpp

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @file   Cylinder.cpp
00003    @author Travis Fischer (fisch0920@gmail.com)
00004    @author Matthew Jacobs (jacobs.mh@gmail.com)
00005    @date   Fall 2008
00006    
00007    @brief
00008       Representation of a vertical 3D cylinder enclosed in the unit box 
00009    (-.5,-.5,-.5) to (.5,.5,.5)
00010    <!-------------------------------------------------------------------->**/
00011 
00012 #include "Cylinder.h"
00013 #include "SurfacePoint.h"
00014 
00015 real_t Cylinder::getIntersection(const Ray &ray, SurfacePoint &pt) {
00016    Point3  P;
00017    Vector3 D;
00018    _transformRayWorldToObj(ray, P, D);
00019    
00020    // A = (Dx^2 + Dz^2)
00021    const real_t A = 2 * (D[0] * D[0] + D[2] * D[2]);
00022    
00023    // B = (2 * Px * Dx + 2 * Pz * Dz)
00024    const real_t B = 2 * (P[0] * D[0] + P[2] * D[2]);
00025    
00026    // C = (Px^2 + Pz^2 - 4)
00027    const real_t C = (P[0] * P[0] + P[2] * P[2] - 0.25);
00028    
00029    // Discriminant of quadratic = B^2 - 4 * A * C
00030    real_t discriminant = B * B - 2 * A * C;
00031    real_t minT = DBL_MAX;
00032    
00033    // Check for intersection with Cylinder Body
00034    // =========================================
00035    if (discriminant >= 0) {
00036       discriminant = sqrt(discriminant);
00037       
00038       const real_t t1 = (-B + discriminant) / A;
00039       const Point3 &p1 = P + t1 * D;
00040       if (p1[1] > -0.5 && p1[1] < 0.5 && t1 > INTERSECT_TOLERANCE) {
00041          minT = t1;
00042       }
00043        
00044       const real_t t2 = (-B - discriminant) / A;
00045       if (isValidT(t2, minT)) {
00046          const Point3 &p2 = P + t2 * D;
00047          
00048          // This is the only one every getting chosen as intersection T?
00049          if (p2[1] > -0.5 && p2[1] < 0.5)
00050             minT = t2;
00051       }
00052    }
00053    
00054    // Check for intersection with Cylinder Caps
00055    // =========================================
00056    const real_t botCapT = (-0.5 - P[1]) / D[1];
00057    const Point3 &intersection4 = P + botCapT * D;
00058    
00059    if ((pt.normalCase = (isValidT(botCapT, minT) && intersection4[0] * intersection4[0] + 
00060                          intersection4[2] * intersection4[2] <= 0.25)))
00061       minT = botCapT;
00062    
00063    const real_t topCapT = (0.5 - P[1]) / D[1];
00064    
00065    // For caps: x^2 + z^2 <= (1/2)^2  must hold for valid intersection point
00066    // note: supposed to be assignment equals '=' on next line
00067    if (isValidT(topCapT, minT)) {
00068       const Point3 &intersection3 = P + topCapT * D;
00069       
00070       if (intersection3[0] * intersection3[0] + intersection3[2] * intersection3[2] <= 0.25) {
00071          pt.normalCase = 2;
00072          minT = topCapT;
00073       }
00074    }
00075    
00076    return minT;
00077 }
00078 
00079 bool Cylinder::intersects(const Ray &ray, real_t tMax) {
00080    Point3  P;
00081    Vector3 D;
00082    _transformRayWorldToObj(ray, P, D);
00083    
00084    // Check for intersection with Cylinder Caps
00085    // -----------------------------------------
00086    const real_t topCapT = (0.5 - P[1]) / D[1];
00087    
00088    // For caps: x^2 + z^2 <= (1/2)^2  must hold for valid intersection point
00089    if (isValidT(topCapT, tMax)) {
00090       const Point3 &intersection3 = P + topCapT * D;
00091       
00092       if (intersection3[0] * intersection3[0] + intersection3[2] * intersection3[2] <= 0.25)
00093          return true;
00094    }
00095    
00096    const real_t botCapT = (-0.5 - P[1]) / D[1];
00097    
00098    if (isValidT(botCapT, tMax)) {
00099       const Point3 &intersection4 = P + botCapT * D;
00100       
00101       if (intersection4[0] * intersection4[0] + intersection4[2] * intersection4[2] <= 0.25)
00102          return true;
00103    }
00104    
00105    // A = (Dx^2 + Dz^2)
00106    const real_t A = 2 * (D[0] * D[0] + D[2] * D[2]);
00107    
00108    // B = (2 * Px * Dx + 2 * Pz * Dz)
00109    const real_t B = 2 * (P[0] * D[0] + P[2] * D[2]);
00110    
00111    // C = (Px^2 + Pz^2 - 1/4)
00112    const real_t C = (P[0] * P[0] + P[2] * P[2] - 0.25);
00113    
00114    // Discriminant of quadratic = B^2 - 4 * A * C
00115    real_t discriminant = B * B - 2 * A * C;
00116    
00117    // Check for intersection with Cylinder Body
00118    // -----------------------------------------
00119    if (discriminant >= 0) {
00120       discriminant = sqrt(discriminant);
00121       
00122       const real_t t1 = (-B + discriminant) / A;
00123       if (isValidT(t1, tMax)) {
00124          const Point3 &p1 = P + t1 * D;
00125          
00126          if (p1[1] > -0.5 && p1[1] < 0.5)
00127             return true;
00128       }
00129       
00130       const real_t t2 = (-B - discriminant) / A;
00131       if (isValidT(t2, tMax)) {
00132          const Point3 &p2 = P + t2 * D;
00133          
00134          return (p2[1] > -0.5 && p2[1] < 0.5);
00135       }
00136    }
00137    
00138    return false;
00139 }
00140 
00141 void Cylinder::_getUV(SurfacePoint &pt) const {
00142    const Point3 &P = pt.position;
00143    real_t &u = pt.uv.u, &v = pt.uv.v;
00144    
00145    if (pt.normalCase) {  // Cylinder or Cone Cap
00146       v = P[2] + 0.5;
00147       u = P[0] + 0.5;
00148       
00149       if (pt.normalCase == 1)
00150          v = 1 - v;
00151    } else {  // Cylinder or Cone Body
00152       u = 1 - atan2(P[2], P[0]) * (1.0 / (2 * M_PI));
00153       v = 0.5 - P[1];  // height up body
00154    }
00155 }
00156 
00157 void Cylinder::_getGeometricNormal(SurfacePoint &pt) const {
00158    Vector3 nObj;
00159    
00160    if (pt.normalCase) {
00161       nObj[1] = 1 - ((pt.normalCase == 1) * 2);
00162    } else {
00163       const Point3 &P = pt.position;
00164       
00165       nObj[0] = P[0];
00166       nObj[2] = P[2];
00167    }
00168    
00169    _transformVector3ObjToWorld(nObj, pt.normalG);
00170 }
00171 
00172 void Cylinder::preview() {
00173    Transformable::preview();
00174    
00175    if (m_quadric == NULL)
00176       m_quadric = gluNewQuadric();
00177    
00178    ASSERT(m_quadric != NULL);
00179    
00180    glRotated(-90, 1, 0, 0);
00181    glTranslated(0, 0, -.5);
00182    gluCylinder(m_quadric, 0.5, 0.5, 1, 20, 20);
00183 }
00184 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6