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 "primitive.h"
00026 #include "paramset.h"
00027 #include "dynload.h"
00028
00029 using namespace lux;
00030
00031
00032 Shape::Shape(const Transform &o2w, bool ro)
00033 : ObjectToWorld(o2w), WorldToObject(o2w.GetInverse()),
00034 reverseOrientation(ro),
00035 transformSwapsHandedness(o2w.SwapsHandedness()) {
00036 }
00037 Shape::Shape(const Transform &o2w, bool ro, boost::shared_ptr<Material> mat)
00038 : ObjectToWorld(o2w), WorldToObject(o2w.GetInverse()),
00039 reverseOrientation(ro),
00040 transformSwapsHandedness(o2w.SwapsHandedness()),
00041 material(mat)
00042 {
00043
00044
00045
00046 }
00047
00048
00049 PrimitiveSet::PrimitiveSet(boost::shared_ptr<Aggregate> a) {
00050 a->GetPrimitives(primitives);
00051
00052 initAreas();
00053
00054 accelerator = a;
00055 }
00056 PrimitiveSet::PrimitiveSet(const vector<boost::shared_ptr<Primitive> > &p) {
00057 primitives = p;
00058
00059 initAreas();
00060
00061
00062 if(primitives.size() <= 16) {
00063 accelerator = boost::shared_ptr<Primitive>((Primitive*)NULL);
00064 worldbound = BBox();
00065 for(u_int i = 0; i < primitives.size(); i++)
00066 worldbound = Union(worldbound, primitives[i]->WorldBound());
00067
00068 worldbound.pMin -= (worldbound.pMax-worldbound.pMin)*0.01f;
00069 worldbound.pMax += (worldbound.pMax-worldbound.pMin)*0.01f;
00070 } else {
00071 accelerator = boost::shared_ptr<Primitive>(
00072 MakeAccelerator("kdtree", primitives, ParamSet()));
00073 if (!accelerator)
00074 luxError(LUX_BUG,LUX_SEVERE,"Unable to find \"kdtree\" accelerator");
00075 }
00076 }
00077 bool PrimitiveSet::Intersect(const Ray &ray, Intersection *in) const {
00078 if(accelerator) {
00079 return accelerator->Intersect(ray, in);
00080 } else if(worldbound.IntersectP(ray)) {
00081
00082 bool anyHit = false;
00083 for (u_int i = 0; i < primitives.size(); ++i) {
00084 if (primitives[i]->Intersect(ray, in)) {
00085 anyHit = true;
00086 }
00087 }
00088 return anyHit;
00089 }
00090 return false;
00091 }
00092
00093 bool PrimitiveSet::IntersectP(const Ray &ray) const {
00094 if(accelerator) {
00095 return accelerator->IntersectP(ray);
00096 } else if(worldbound.IntersectP(ray)) {
00097 for (u_int i = 0; i < primitives.size(); ++i) {
00098 if (primitives[i]->IntersectP(ray)) {
00099 return true;
00100 }
00101 }
00102 }
00103 return false;
00104 }
00105
00106 void PrimitiveSet::initAreas() {
00107 area = 0;
00108 vector<float> areas;
00109 areas.reserve(primitives.size());
00110 for (u_int i = 0; i < primitives.size(); ++i) {
00111 float a = primitives[i]->Area();
00112 area += a;
00113 areas.push_back(a);
00114 }
00115 float prevCDF = 0;
00116 areaCDF.reserve(primitives.size());
00117 for (u_int i = 0; i < primitives.size(); ++i) {
00118 areaCDF.push_back(prevCDF + areas[i] / area);
00119 prevCDF = areaCDF[i];
00120 }
00121 }