Cone.cpp

Go to the documentation of this file.
00001 /**<!-------------------------------------------------------------------->
00002    @file   Cone.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 cone enclosed in the unit box 
00009    (-.5,-.5,-.5) to (.5,.5,.5) -- the tip is at (0,.5,0)
00010    <!-------------------------------------------------------------------->**/
00011 
00012 #include "Cone.h"
00013 #include "SurfacePoint.h"
00014 
00015 real_t Cone::getIntersection(const Ray &ray, SurfacePoint &pt) {
00016    Point3  P;
00017    Vector3 D;
00018    _transformRayWorldToObj(ray, P, D);
00019    
00020    // A = (Dx^2 + Dz^2 - 1/4 * Dy^2)
00021    const real_t A = 2 * (D[0] * D[0] + D[2] * D[2] - 0.25 * D[1] * D[1]);
00022 
00023    // B = (2 * Px * Dx + 2 * Pz * Dz - 1/2 * Py * Dy + 1/4 * Dy)
00024    const real_t B = (2 * P[0] * D[0] + 2 * P[2] * D[2] - 0.5 * P[1] * D[1] + 0.25 * D[1]);
00025 
00026    // C = (Px^2 + Pz^2 - 1/4 * Py^2 + 1/4 * Py - 1/16)
00027    const real_t C = (P[0] * P[0] + P[2] * P[2] - 0.25 * P[1] * P[1] + 0.25 * P[1] - 0.0625);
00028 
00029    // Discriminant of quadratic = B^2 - 4 * A * C
00030    real_t discriminant =  B * B - 2 * A * C;
00031    real_t minT = INFINITY;
00032 
00033    // Check for intersection with Cone 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[2] < 0.5 && p1[2] > -0.5 && p1[1] > -0.5 && p1[1] < 0.5 && t1 > INTERSECT_TOLERANCE)
00041          minT = t1;
00042 
00043       const real_t t2 = (-B - discriminant) / A;
00044 
00045       if (isValidT(t2, minT)) {
00046          const Point3 &p2 = P + t2 * D;
00047          
00048          if (p2[2] < 0.5 && p2[2] > -0.5 && p2[1] > -0.5 && p2[1] < 0.5)
00049             minT = t2;
00050       }
00051    }
00052    
00053    // Check for intersection with Cone Cap
00054    // ------------------------------------
00055    const real_t tCap = (-0.5 - P[1]) / D[1];
00056    
00057    pt.normalCase = 0;
00058    if (isValidT(tCap, minT)) {
00059       const Point3 &intersection3 = P + tCap * D;
00060       // For Cone Cap: x^2 + z^2 <= (1/2)^2  must hold for valid intersection point
00061       
00062       if (intersection3[0] * intersection3[0] +
00063           intersection3[2] * intersection3[2] <= 0.25) {
00064          pt.normalCase = 1;
00065          return tCap;
00066       }
00067    }
00068    
00069    return minT;
00070 }
00071 
00072 bool Cone::intersects(const Ray &ray, real_t tMax) {
00073    Point3  P;
00074    Vector3 D;
00075    _transformRayWorldToObj(ray, P, D);
00076    
00077    // Check for intersection with Cone Cap
00078    // ------------------------------------
00079    const real_t tCap = (-0.5 - P[1]) / D[1];
00080    
00081    if (isValidT(tCap, tMax)) {
00082       const Point3 &intersection3 = P + tCap * D;
00083       
00084       // For Cone Cap: x^2 + z^2 <= (1/2)^2  must hold for valid intersection point
00085       if (intersection3[0] * intersection3[0] + intersection3[2] * intersection3[2] <= 0.25)
00086          return true;
00087    }
00088    
00089    // A = (Dx^2 + Dz^2 - 1/4 * Dy^2)
00090    const real_t A = 2 * (D[0] * D[0] + D[2] * D[2] - 0.25 * D[1] * D[1]);
00091    
00092    // B = (2 * Px * Dx + 2 * Pz * Dz - 1/2 * Py * Dy + 1/4 * Dy)
00093    const real_t B = (2 * P[0] * D[0] + 2 * P[2] * D[2] - 0.5 * P[1] * D[1] + 0.25 * D[1]);
00094    
00095    // C = (Px^2 + Pz^2 - 1/4 * Py^2 + 1/4 * Py - 1/16)
00096    const real_t C = (P[0] * P[0] + P[2] * P[2] - 0.25 * P[1] * P[1] + 0.25 * P[1] - 0.0625);
00097    
00098    // Discriminant of quadratic = B^2 - 4 * A * C
00099    real_t discriminant =  B * B - 2 * A * C;
00100    
00101    // Check for intersection with Cone Body
00102    // -------------------------------------
00103    if (discriminant >= 0) {
00104       discriminant = sqrt(discriminant);
00105       
00106       const real_t t1 = (-B + discriminant) / A;
00107       if (isValidT(t1, tMax)) {
00108          const Point3 &p1 = P + t1 * D;
00109          
00110          if (p1[2] < 0.5 && p1[2] > -0.5 && p1[1] > -0.5 && p1[1] < 0.5)
00111             return true;
00112       }
00113       
00114       const real_t t2 = (-B - discriminant) / A;
00115       if (isValidT(t2, tMax)) {
00116          const Point3 &p2 = P + t2 * D;
00117          return (p2[2] < 0.5 && p2[2] > -0.5 && p2[1] > -0.5 && p2[1] < 0.5);
00118       }
00119    }
00120    
00121    return false;
00122 }
00123 
00124 void Cone::_getUV(SurfacePoint &pt) const {
00125    const Point3 &P = pt.position;
00126    real_t &u = pt.uv.u, &v = pt.uv.v;
00127    
00128    if (pt.normalCase) {  // Cylinder or Cone Cap
00129       v = P[2] + 0.5;
00130       u = P[0] + 0.5;
00131       
00132       if (pt.normalCase == 1)
00133          v = 1 - v;
00134    } else {  // Cylinder or Cone Body
00135       u = 1 - atan2(P[2], P[0]) * (1.0 / (2 * M_PI));
00136       v = 0.5 - P[1];  // height up body
00137    }
00138 }
00139 
00140 void Cone::_getGeometricNormal(SurfacePoint &pt) const {
00141    Vector3 nObj;
00142    
00143    if (pt.normalCase) {
00144       nObj[1] = 1 - ((pt.normalCase == 1) * 2);
00145    } else {
00146       const Point3 &P = pt.position;
00147       const real_t m  = 1 / sqrt(P[0] * P[0] + P[2] * P[2]);
00148       
00149       nObj = Vector3(P[0] * m, .5, P[2] * m);
00150    }
00151    
00152    _transformVector3ObjToWorld(nObj, pt.normalG);
00153 }
00154 
00155 void Cone::preview() {
00156    Transformable::preview();
00157    
00158    if (m_quadric == NULL)
00159       m_quadric = gluNewQuadric();
00160    
00161    ASSERT(m_quadric != NULL);
00162    
00163    glRotated(-90, 1, 0, 0);
00164    glTranslated(0, 0, -.5);
00165    gluCylinder(m_quadric, 0.5, 0.0, 1, 20, 20);
00166 }
00167 

Generated on 28 Feb 2009 for Milton by doxygen 1.5.6