00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "shape.h"
00025 #include "mc.h"
00026
00027 namespace lux
00028 {
00029
00030
00031 class Sphere: public Shape {
00032 public:
00033
00034 Sphere(const Transform &o2w, bool ro, float rad,
00035 float zmin, float zmax, float phiMax);
00036 virtual ~Sphere() { }
00037 virtual BBox ObjectBound() const;
00038 virtual bool Intersect(const Ray &ray, float *tHit,
00039 DifferentialGeometry *dg) const;
00040 virtual bool IntersectP(const Ray &ray) const;
00041 virtual float Area() const;
00042 virtual Point Sample(float u1, float u2, float u3, Normal *ns) const {
00043 Point p = Point(0,0,0) + radius *
00044 UniformSampleSphere(u1, u2);
00045 *ns = Normalize(ObjectToWorld(Normal(p.x, p.y, p.z)));
00046 if (reverseOrientation) *ns *= -1.f;
00047 return ObjectToWorld(p);
00048 }
00049 virtual Point Sample(const Point &p,
00050 float u1, float u2, float u3, Normal *ns) const {
00051
00052 Point Pcenter = ObjectToWorld(Point(0,0,0));
00053 Vector wc = Normalize(Pcenter - p);
00054 Vector wcX, wcY;
00055 CoordinateSystem(wc, &wcX, &wcY);
00056
00057 if (DistanceSquared(p, Pcenter) - radius*radius < 1e-4f)
00058 return Sample(u1, u2, u3, ns);
00059
00060 float cosThetaMax = sqrtf(max(0.f, 1.f - radius*radius /
00061 DistanceSquared(p, Pcenter)));
00062 DifferentialGeometry dgSphere;
00063 float thit;
00064 Point ps;
00065 Ray r(p,
00066 UniformSampleCone(u1, u2, cosThetaMax, wcX, wcY, wc));
00067 if (!Intersect(r, &thit, &dgSphere)) {
00068 ps = Pcenter - radius * wc;
00069 } else {
00070 ps = r(thit);
00071 }
00072 *ns = Normal(Normalize(ps - Pcenter));
00073 if (reverseOrientation) *ns *= -1.f;
00074 return ps;
00075 }
00076 virtual float Pdf(const Point &p, const Vector &wi) const {
00077 Point Pcenter = ObjectToWorld(Point(0,0,0));
00078
00079 if (DistanceSquared(p, Pcenter) - radius*radius < 1e-4f)
00080 return Shape::Pdf(p, wi);
00081
00082 float cosThetaMax = sqrtf(max(0.f, 1.f - radius*radius /
00083 DistanceSquared(p, Pcenter)));
00084 return UniformConePdf(cosThetaMax);
00085 }
00086 virtual float Pdf(const Point &p, const Point &po) const {
00087 Point Pcenter = ObjectToWorld(Point(0,0,0));
00088
00089 if (DistanceSquared(p, Pcenter) - radius*radius < 1e-4f)
00090 return Shape::Pdf(p, po);
00091
00092 const float cosThetaMax = sqrtf(max(0.f, 1.f - radius*radius /
00093 DistanceSquared(p, Pcenter)));
00094 const Vector w(p - po);
00095 const float d2 = w.LengthSquared();
00096 return UniformConePdf(cosThetaMax) * AbsDot(w, po - Pcenter) /
00097 (d2 * sqrtf(d2) * radius);
00098 }
00099
00100 static Shape* CreateShape(const Transform &o2w, bool reverseOrientation, const ParamSet ¶ms);
00101 private:
00102
00103 float radius;
00104 float phiMax;
00105 float zmin, zmax;
00106 float thetaMin, thetaMax;
00107 };
00108
00109 }