00001 #include "Sphere.h" 00002 #include <limits> 00003 #include <cmath> 00004 #include <iostream> 00005 00006 using namespace std; 00007 00008 namespace rcrt 00009 { 00010 00011 00012 Sphere::Sphere(const Point3D& c, float r, SolidObject* parent):Primitive(parent),center(c),radius(r) 00013 { 00014 box.extend(center+Vec3D(radius,radius,radius)); 00015 box.extend(center-Vec3D(radius,radius,radius)); 00016 } 00017 00018 00019 Sphere::Sphere(const Sphere& s, SolidObject* parent):Primitive(parent) 00020 { 00021 assign(s); 00022 } 00023 00024 00025 Sphere::~Sphere() 00026 { 00027 } 00028 00029 00030 void Sphere::assign(const Sphere& s) 00031 { 00032 center = s.center; 00033 radius = s.radius; 00034 } 00035 00036 Intersection Sphere::intersect(Ray& ray) const 00037 { 00038 Vec3D v = ray.org() - center; 00039 float b = -( v * ray.dir()); 00040 float det = (b * b) - v * v + radius * radius; 00041 if (det <= 0) 00042 return Intersection(); 00043 else { 00044 det = sqrt( det ); 00045 float i1 = b - det; 00046 float i2 = b + det; 00047 if (i2 <= 0) 00048 return Intersection(); 00049 else { 00050 if (i1 < 0) 00051 { 00052 Point3D hitP(ray.atDistance(i2)); 00053 Vec3D vec = (hitP-center).normalize(); 00054 float theta = acos(vec.z()); 00055 float phi = atan2(vec.y(),vec.x()); 00056 if(phi < 0) 00057 phi += 2*M_PI; 00058 Intersection is(i2, this, hitP, theta, phi, true); 00059 is.setSNormalL(vec); 00060 is.setGNormalL(vec); 00061 return is; 00062 } 00063 else 00064 { 00065 Point3D hitP(ray.atDistance(i1)); 00066 Vec3D vec = (hitP-center).normalize(); 00067 float theta = acos(vec.z()); 00068 float phi = atan2(vec.y(),vec.x()); 00069 if(phi < 0) 00070 phi += 2*M_PI; 00071 Intersection is(i1, this, hitP, theta, phi, false); 00072 is.setSNormalL(vec); 00073 is.setGNormalL(vec); 00074 return is; 00075 } 00076 } 00077 } 00078 } 00079 00080 00081 const AABB& Sphere::getBoundingBox() const 00082 { 00083 return box; 00084 } 00085 00086 00087 const Point3D& Sphere::getCentroid() const 00088 { 00089 return center; 00090 } 00091 00092 float Sphere::getRadius() const 00093 { 00094 return radius; 00095 } 00096 00097 Vec3D Sphere::getSNormal(float theta, float phi) const 00098 { 00099 return getGNormal(theta, phi); 00100 } 00101 00102 Vec3D Sphere::getGNormal(float theta, float phi) const 00103 { 00104 Vec3D no(cos(phi) * sin(theta), 00105 sin(phi) * sin(theta), 00106 cos(theta)); 00107 no.normalize(); 00108 return no; 00109 } 00110 00111 Point2D Sphere::getUV(float theta, float phi) const 00112 { 00113 return Point2D(phi/(2*M_PI), theta/M_PI); 00114 } 00115 00116 AABB Sphere::clipBox(AABB& cbox) const { 00117 return getBoundingBox(); 00118 } 00119 00120 }