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 }