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
1.5.6