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