Sphere.cpp
Go to the documentation of this file.00001 /**<!--------------------------------------------------------------------> 00002 @file Sphere.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 3D sphere with radius .5, enclosed in the unit box 00009 (-.5,-.5,-.5) to (.5,.5,.5) 00010 <!-------------------------------------------------------------------->**/ 00011 00012 #include "Sphere.h" 00013 #include <SurfacePoint.h> 00014 00015 real_t Sphere::getIntersection(const Ray &ray, SurfacePoint &pt) { 00016 Point3 P; 00017 Vector3 D; 00018 _transformRayWorldToObj(ray, P, D); 00019 00020 // A = (Dx^2 + Dy^2 + Dz^2) 00021 const real_t A = 2 * (D[0] * D[0] + D[1] * D[1] + D[2] * D[2]); 00022 00023 // B = (2 * Px * Dx + 2 * Py * Dy + 2 * Pz * Dz) 00024 const real_t B = -2 * (P[0] * D[0] + P[1] * D[1] + P[2] * D[2]); 00025 00026 // C = (Px^2 + Py^s + Pz^2 - 1/4) 00027 const real_t C = (P[0] * P[0] + P[1] * P[1] + 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 00032 // Check for intersection with Sphere Body 00033 // --------------------------------------- 00034 if (discriminant < 0) 00035 return INFINITY; 00036 00037 discriminant = sqrt(discriminant); 00038 const real_t F = 1 / A; 00039 real_t t = (B - discriminant) * F; 00040 00041 return ((t > INTERSECT_TOLERANCE || 00042 (t = (B + discriminant) * F) > INTERSECT_TOLERANCE) 00043 ? t : INFINITY); 00044 } 00045 00046 bool Sphere::intersects(const Ray &ray, real_t tMax) { 00047 Point3 P; 00048 Vector3 D; 00049 _transformRayWorldToObj(ray, P, D); 00050 00051 // A = (Dx^2 + Dy^2 + Dz^2) 00052 const real_t A = 2 * (D[0] * D[0] + D[1] * D[1] + D[2] * D[2]); 00053 00054 // B = (2 * Px * Dx + 2 * Py * Dy + 2 * Pz * Dz) 00055 const real_t B = -2 * (P[0] * D[0] + P[1] * D[1] + P[2] * D[2]); 00056 00057 // C = (Px^2 + Py^s + Pz^2 - 1/4) 00058 const real_t C = (P[0] * P[0] + P[1] * P[1] + P[2] * P[2] - 0.25); 00059 00060 // Discriminant of quadratic = B^2 - 4 * A * C 00061 real_t discriminant = B * B - 2 * A * C; 00062 00063 // Check for intersection with Sphere Body 00064 // --------------------------------------- 00065 00066 if (discriminant >= 0) { 00067 discriminant = sqrt(discriminant); 00068 const real_t F = 1 / A; 00069 00070 real_t t = (B + discriminant) * F; 00071 return (isValidT(t, tMax) || 00072 ((t = (B - discriminant) * F) < tMax && t > INTERSECT_TOLERANCE)); 00073 } 00074 00075 return false; 00076 } 00077 00078 void Sphere::_getUV(SurfacePoint &pt) const { 00079 Point3 P; 00080 _transformPoint3WorldToObj(pt.position, P); 00081 real_t &u = pt.uv.u, &v = pt.uv.v; 00082 00083 u = 1 - atan2(P[2], P[0]) * (1 / (2 * M_PI)); 00084 v = 0.5 - asin(P[1] * 2) * (1 / M_PI); 00085 } 00086 00087 void Sphere::_getGeometricNormal(SurfacePoint &pt) const { 00088 Point3 P; 00089 _transformPoint3WorldToObj(pt.position, P); 00090 Vector3 nObj(P[0], P[1], P[2]); 00091 00092 _transformVector3ObjToWorld(nObj, pt.normalG); 00093 } 00094 00095 void Sphere::preview() { 00096 Transformable::preview(); 00097 00098 if (m_quadric == NULL) 00099 m_quadric = gluNewQuadric(); 00100 00101 ASSERT(m_quadric != NULL); 00102 00103 gluSphere(m_quadric, 0.5, 20, 20); 00104 } 00105 00106 void Sphere::getRandomPoint(SurfacePoint &pt) { 00107 if (!m_surfaceSampler) 00108 m_surfaceSampler = new UniformOnSphereSampler(); 00109 00110 pt.position = m_transToWorld * m_surfaceSampler->sample().getValue<Point3>(); 00111 _getUV(pt); 00112 00113 getPoint(pt, pt.uv); 00114 } 00115 00116 Point3 Sphere::getPosition(const UV &uv) { 00117 real_t x = CAP(tan((1.0 - uv.u) / (2 * M_PI)), -.5, .5); 00118 real_t y = CAP(sin((0.5 - uv.v) / M_PI) * 0.5, -.5, .5); 00119 real_t z = sqrt(1 - x * x - y * y); 00120 00121 // TODO: verify correctness for x and z (inversing atan2) 00122 return m_transToWorld * Point3(x, y, z); 00123 } 00124 00125 #if 0 00126 Vector3 Sphere::getNormal(const Point3 &pt) const { 00127 const Point3 &ptObj = m_transToWorldInv * pt; 00128 Vector3 nObj(ptObj.data), nWorld; 00129 00130 // TODO: shouldn't need to normalize nObj before transformation 00131 _transformVector3ObjToWorld(nObj, nWorld); 00132 00133 return nWorld; 00134 } 00135 #endif 00136 00137 real_t Sphere::_getSurfaceArea() { 00138 // TODO return surface area in world-space!!! 00139 return (4 * M_PI * 0.25); // 4*pi*r^2 00140 } 00141
Generated on 28 Feb 2009 for Milton by
1.5.6