00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef LUX_SHAPE_H
00024 #define LUX_SHAPE_H
00025
00026 #include "lux.h"
00027 #include "geometry.h"
00028 #include "error.h"
00029
00030 namespace lux
00031 {
00032
00033
00034 class DifferentialGeometry {
00035 public:
00036
00037 DifferentialGeometry() { u = v = 0.; shape = NULL; }
00038
00039 DifferentialGeometry(const Point &P, const Vector &DPDU,
00040 const Vector &DPDV, const Vector &DNDU,
00041 const Vector &DNDV, float uu, float vv,
00042 const Shape *sh);
00043 DifferentialGeometry(const Point &P, const Normal &NN,
00044 const Vector &DPDU, const Vector &DPDV,
00045 const Vector &DNDU, const Vector &DNDV,
00046 float uu, float vv,
00047 const Shape *sh);
00048 void ComputeDifferentials(const RayDifferential &r) const;
00049
00050 Point p;
00051 Normal nn;
00052 Vector dpdu, dpdv;
00053 Normal dndu, dndv;
00054 mutable Vector dpdx, dpdy;
00055 float u, v;
00056 const Shape *shape;
00057 mutable float dudx, dvdx, dudy, dvdy;
00058 };
00059
00060
00061 class Shape {
00062 public:
00063
00064 Shape(const Transform &o2w, bool ro);
00065 virtual ~Shape() { }
00066 virtual BBox ObjectBound() const = 0;
00067 virtual BBox WorldBound() const {
00068 return ObjectToWorld(ObjectBound());
00069 }
00070 virtual bool CanIntersect() const { return true; }
00071 virtual void
00072 Refine(vector<boost::shared_ptr<Shape> > &refined) const {
00073
00074 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Shape::Refine() method called");
00075 }
00076 virtual bool Intersect(const Ray &ray, float *tHit,
00077 DifferentialGeometry *dg) const {
00078 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Shape::Intersect() method called");
00079 return false;
00080 }
00081 virtual bool IntersectP(const Ray &ray) const {
00082 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Shape::IntersectP() method called");
00083 return false;
00084 }
00085 virtual void GetShadingGeometry(const Transform &obj2world,
00086 const DifferentialGeometry &dg,
00087 DifferentialGeometry *dgShading) const {
00088 *dgShading = dg;
00089 }
00090 virtual float Area() const {
00091 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Shape::Area() method called");
00092 return 0.;
00093 }
00094 virtual Point Sample(float u1, float u2, Normal *Ns) const {
00095 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Shape::Sample method called");
00096 return Point();
00097 }
00098 virtual float Pdf(const Point &Pshape) const {
00099 return 1.f / Area();
00100 }
00101 virtual Point Sample(const Point &P,
00102 float u1, float u2, Normal *Ns) const {
00103 return Sample(u1, u2, Ns);
00104 }
00105 virtual float Pdf(const Point &p, const Vector &wi) const {
00106
00107 DifferentialGeometry dgLight;
00108 Ray ray(p, wi);
00109 float thit;
00110 if (!Intersect(ray, &thit, &dgLight)) return 0.;
00111
00112 float pdf = DistanceSquared(p, ray(thit)) /
00113 (AbsDot(dgLight.nn, -wi) * Area());
00114 if (AbsDot(dgLight.nn, -wi) == 0.f) pdf = INFINITY;
00115 return pdf;
00116 }
00117
00118 const Transform ObjectToWorld, WorldToObject;
00119 const bool reverseOrientation, transformSwapsHandedness;
00120 };
00121 class ShapeSet : public Shape {
00122 public:
00123
00124 Point Sample(float u1, float u2, Normal *Ns) const {
00125 float ls = lux::random::floatValue();
00126 u_int sn;
00127 for (sn = 0; sn < shapes.size()-1; ++sn)
00128 if (ls < areaCDF[sn]) break;
00129 return shapes[sn]->Sample(u1, u2, Ns);
00130 }
00131 ShapeSet(const vector<boost::shared_ptr<Shape> > &s,
00132 const Transform &o2w, bool ro);
00133 BBox ObjectBound() const {
00134 BBox ob;
00135 for (u_int i = 0; i < shapes.size(); ++i)
00136 ob = Union(ob, shapes[i]->ObjectBound());
00137 return ob;
00138 }
00139 bool CanIntersect() const {
00140 for (u_int i = 0; i < shapes.size(); ++i)
00141 if (!shapes[i]->CanIntersect()) return false;
00142 return true;
00143 }
00144 bool Intersect(const Ray &ray, float *t_hitp,
00145 DifferentialGeometry *dg) const;
00146 void Refine(vector<boost::shared_ptr<Shape> > &refined) const {
00147 for (u_int i = 0; i < shapes.size(); ++i) {
00148 if (shapes[i]->CanIntersect())
00149 refined.push_back(shapes[i]);
00150 else shapes[i]->Refine(refined);
00151 }
00152
00153 }
00154 float Area() const { return area; }
00155 private:
00156
00157 float area;
00158 vector<float> areaCDF;
00159 vector<boost::shared_ptr<Shape> > shapes;
00160 BBox worldbound;
00161 Primitive *accelerator;
00162 };
00163
00164 }
00165
00166 #endif // LUX_SHAPE_H