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 "primitive.h"
00028 #include "error.h"
00029
00030 namespace lux
00031 {
00032
00033
00034
00035 class Shape : public Primitive {
00036 public:
00037 Shape(const Transform &o2w, bool ro);
00038 Shape(const Transform &o2w, bool ro,
00039 boost::shared_ptr<Material> material);
00040 virtual ~Shape() { }
00041
00042 void SetMaterial(boost::shared_ptr<Material> mat) { this->material = mat; }
00043 boost::shared_ptr<Material> GetMaterial() const { return material; }
00044
00045 virtual BBox WorldBound() const { return ObjectToWorld(ObjectBound()); }
00046 virtual void Refine(vector<boost::shared_ptr<Primitive> > &refined,
00047 const PrimitiveRefinementHints& refineHints,
00048 boost::shared_ptr<Primitive> thisPtr)
00049 {
00050 vector<boost::shared_ptr<Shape> > todo;
00051 Refine(todo);
00052 for(u_int i=0; i<todo.size(); i++) {
00053 boost::shared_ptr<Shape> shape = todo[i];
00054 shape->SetMaterial(this->material);
00055 if (shape->CanIntersect()) {
00056 refined.push_back(shape);
00057 }
00058 else {
00059
00060 shape->Refine(refined, refineHints, shape);
00061 }
00062 }
00063 }
00064
00065 virtual bool CanIntersect() const { return true; }
00066 virtual bool Intersect(const Ray &r, Intersection *isect) const {
00067 float thit;
00068 if (!Intersect(r, &thit, &isect->dg))
00069 return false;
00070 isect->dg.AdjustNormal(reverseOrientation, transformSwapsHandedness);
00071 isect->Set(WorldToObject, this, material.get());
00072 r.maxt = thit;
00073 return true;
00074 }
00075
00076 virtual void GetShadingGeometry(const Transform &obj2world,
00077 const DifferentialGeometry &dg,
00078 DifferentialGeometry *dgShading) const
00079 {
00080 *dgShading = dg;
00081 }
00082
00083 virtual bool CanSample() const { return true; }
00084 virtual void Sample(float u1, float u2, float u3, DifferentialGeometry *dg) const {
00085 dg->p = Sample(u1, u2, u3, &dg->nn);
00086 CoordinateSystem(Vector(dg->nn), &dg->dpdu, &dg->dpdv);
00087
00088 dg->u = dg->v = .5f;
00089 }
00090 virtual void Sample(const Point &p, float u1, float u2, float u3, DifferentialGeometry *dg) const {
00091 dg->p = Sample(p, u1, u2, u3, &dg->nn);
00092 CoordinateSystem(Vector(dg->nn), &dg->dpdu, &dg->dpdv);
00093
00094 dg->u = dg->v = .5f;
00095 }
00096
00097
00098 virtual BBox ObjectBound() const {
00099 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Shape::ObjectBound method called!");
00100 return BBox();
00101 }
00102 virtual void Refine(vector<boost::shared_ptr<Shape> > &refined) const {
00103 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Shape::Refine() method called");
00104 }
00105 virtual bool Intersect(const Ray &ray, float *t_hitp,
00106 DifferentialGeometry *dg) const
00107 {
00108 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Shape::Intersect() method called");
00109 return false;
00110 }
00111 virtual Point Sample(float u1, float u2, float u3, Normal *Ns) const {
00112 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Shape::Sample() method called");
00113 return Point();
00114 }
00115 virtual Point Sample(const Point &p, float u1, float u2, float u3, Normal *Ns) const {
00116 return Sample(u1, u2, u3, Ns);
00117 }
00118
00119 const Transform ObjectToWorld, WorldToObject;
00120 const bool reverseOrientation, transformSwapsHandedness;
00121 protected:
00122 boost::shared_ptr<Material> material;
00123 };
00124
00125 class PrimitiveSet : public Primitive {
00126 public:
00127
00128 PrimitiveSet(boost::shared_ptr<Aggregate> a);
00129 PrimitiveSet(const vector<boost::shared_ptr<Primitive> > &p);
00130 virtual ~PrimitiveSet() { }
00131
00132 virtual BBox WorldBound() const { return worldbound; }
00133 virtual bool CanIntersect() const {
00134 for (u_int i = 0; i < primitives.size(); ++i)
00135 if (!primitives[i]->CanIntersect()) return false;
00136 return true;
00137 }
00138 virtual bool Intersect(const Ray &r, Intersection *in) const;
00139 virtual bool IntersectP(const Ray &r) const;
00140
00141 virtual bool CanSample() const {
00142 for (u_int i = 0; i < primitives.size(); ++i)
00143 if (!primitives[i]->CanSample()) return false;
00144 return true;
00145 }
00146 virtual void Sample(float u1, float u2, float u3, DifferentialGeometry *dg) const {
00147 u_int sn;
00148 if( primitives.size() <= 16) {
00149 for (sn = 0; sn < primitives.size()-1; ++sn)
00150 if (u3 < areaCDF[sn]) break;
00151 }
00152 else {
00153 sn = Clamp(
00154 (u_int)(std::upper_bound(areaCDF.begin(), areaCDF.end(), u3) - areaCDF.begin()),
00155 (u_int)(0), (u_int)(primitives.size() - 1));
00156 }
00157 primitives[sn]->Sample(u1, u2, u3, dg);
00158 }
00159 virtual float Area() const { return area; }
00160 private:
00161 void initAreas();
00162
00163
00164 float area;
00165 vector<float> areaCDF;
00166 vector<boost::shared_ptr<Primitive> > primitives;
00167 BBox worldbound;
00168 boost::shared_ptr<Primitive> accelerator;
00169 };
00170
00171 }
00172
00173 #endif // LUX_SHAPE_H