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
1.5.6