PBRT
|
00001 00002 // 00003 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas 00004 // Digital Ltd. LLC 00005 // 00006 // All rights reserved. 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are 00010 // met: 00011 // * Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // * Redistributions in binary form must reproduce the above 00014 // copyright notice, this list of conditions and the following disclaimer 00015 // in the documentation and/or other materials provided with the 00016 // distribution. 00017 // * Neither the name of Industrial Light & Magic nor the names of 00018 // its contributors may be used to endorse or promote products derived 00019 // from this software without specific prior written permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00024 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00025 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00027 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00028 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00029 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00030 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00031 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00034 00035 00036 00037 #ifndef INCLUDED_IMATHSPHERE_H 00038 #define INCLUDED_IMATHSPHERE_H 00039 00040 //------------------------------------- 00041 // 00042 // A 3D sphere class template 00043 // 00044 //------------------------------------- 00045 00046 #include "ImathVec.h" 00047 #include "ImathBox.h" 00048 #include "ImathLine.h" 00049 00050 namespace Imath { 00051 00052 template <class T> 00053 class Sphere3 00054 { 00055 public: 00056 00057 Vec3<T> center; 00058 T radius; 00059 00060 //--------------- 00061 // Constructors 00062 //--------------- 00063 00064 Sphere3() : center(0,0,0), radius(0) {} 00065 Sphere3(const Vec3<T> &c, T r) : center(c), radius(r) {} 00066 00067 //------------------------------------------------------------------- 00068 // Utilities: 00069 // 00070 // s.circumscribe(b) sets center and radius of sphere s 00071 // so that the s tightly encloses box b. 00072 // 00073 // s.intersectT (l, t) If sphere s and line l intersect, then 00074 // intersectT() computes the smallest t, 00075 // t >= 0, so that l(t) is a point on the 00076 // sphere. intersectT() then returns true. 00077 // 00078 // If s and l do not intersect, intersectT() 00079 // returns false. 00080 // 00081 // s.intersect (l, i) If sphere s and line l intersect, then 00082 // intersect() calls s.intersectT(l,t) and 00083 // computes i = l(t). 00084 // 00085 // If s and l do not intersect, intersect() 00086 // returns false. 00087 // 00088 //------------------------------------------------------------------- 00089 00090 void circumscribe(const Box<Vec3<T> > &box); 00091 bool intersect(const Line3<T> &l, Vec3<T> &intersection) const; 00092 bool intersectT(const Line3<T> &l, T &t) const; 00093 }; 00094 00095 00096 //-------------------- 00097 // Convenient typedefs 00098 //-------------------- 00099 00100 typedef Sphere3<float> Sphere3f; 00101 typedef Sphere3<double> Sphere3d; 00102 00103 00104 //--------------- 00105 // Implementation 00106 //--------------- 00107 00108 template <class T> 00109 void Sphere3<T>::circumscribe(const Box<Vec3<T> > &box) 00110 { 00111 center = T(0.5) * (box.min + box.max); 00112 radius = (box.max - center).length(); 00113 } 00114 00115 00116 template <class T> 00117 bool Sphere3<T>::intersectT(const Line3<T> &line, T &t) const 00118 { 00119 bool doesIntersect = true; 00120 00121 Vec3<T> v = line.pos - center; 00122 T B = 2.0 * (line.dir ^ v); 00123 T C = (v ^ v) - (radius * radius); 00124 00125 // compute discriminant 00126 // if negative, there is no intersection 00127 00128 T discr = B*B - 4.0*C; 00129 00130 if (discr < 0.0) 00131 { 00132 // line and Sphere3 do not intersect 00133 00134 doesIntersect = false; 00135 } 00136 else 00137 { 00138 // t0: (-B - sqrt(B^2 - 4AC)) / 2A (A = 1) 00139 00140 T sqroot = Math<T>::sqrt(discr); 00141 t = (-B - sqroot) * 0.5; 00142 00143 if (t < 0.0) 00144 { 00145 // no intersection, try t1: (-B + sqrt(B^2 - 4AC)) / 2A (A = 1) 00146 00147 t = (-B + sqroot) * 0.5; 00148 } 00149 00150 if (t < 0.0) 00151 doesIntersect = false; 00152 } 00153 00154 return doesIntersect; 00155 } 00156 00157 00158 template <class T> 00159 bool Sphere3<T>::intersect(const Line3<T> &line, Vec3<T> &intersection) const 00160 { 00161 T t; 00162 00163 if (intersectT (line, t)) 00164 { 00165 intersection = line(t); 00166 return true; 00167 } 00168 else 00169 { 00170 return false; 00171 } 00172 } 00173 00174 00175 } //namespace Imath 00176 00177 #endif