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
00038
00039 }
00040
00041 ShapeSet::ShapeSet(const vector<boost::shared_ptr<Shape> > &s,
00042 const Transform &o2w, bool ro)
00043 : Shape(o2w, ro) {
00044 shapes = s;
00045 area = 0;
00046 vector<float> areas;
00047 for (u_int i = 0; i < shapes.size(); ++i) {
00048 float a = shapes[i]->Area();
00049 area += a;
00050 areas.push_back(a);
00051 }
00052 float prevCDF = 0;
00053 for (u_int i = 0; i < shapes.size(); ++i) {
00054 areaCDF.push_back(prevCDF + areas[i] / area);
00055 prevCDF = areaCDF[i];
00056 }
00057
00058
00059 if(shapes.size() <= 16) {
00060 accelerator = NULL;
00061 worldbound = WorldBound();
00062
00063 worldbound.pMin -= (worldbound.pMax-worldbound.pMin)*0.01f;
00064 worldbound.pMax += (worldbound.pMax-worldbound.pMin)*0.01f;
00065 } else {
00066 vector<Primitive*> primitives;
00067 for (u_int i = 0; i < shapes.size(); ++i) {
00068 boost::shared_ptr<Material> emptyMtl;
00069 Primitive* prim (new GeometricPrimitive(shapes[i], emptyMtl, NULL));
00070 primitives.push_back(prim);
00071 }
00072 accelerator = MakeAccelerator("kdtree", primitives, ParamSet());
00073 if (!accelerator)
00074 luxError(LUX_BUG,LUX_SEVERE,"Unable to find \"kdtree\" accelerator");
00075 }
00076 }
00077 bool ShapeSet::Intersect(const Ray &ray, float *t_hitp,
00078 DifferentialGeometry *dg) const {
00079 Ray bray = ray;
00080 if(accelerator) {
00081 Intersection isect;
00082 if (!accelerator->Intersect(bray, &isect))
00083 return false;
00084
00085 *t_hitp = bray.maxt;
00086 *dg = isect.dg;
00087 return true;
00088 } else if(worldbound.IntersectP(bray)) {
00089
00090
00091 bool anyHit = false;
00092 for (u_int i = 0; i < shapes.size(); ++i) {
00093 if (shapes[i]->Intersect(bray, t_hitp, dg)) {
00094 bray.maxt = *t_hitp;
00095 anyHit = true;
00096 }
00097 }
00098 return anyHit;
00099 } else {
00100 return false;
00101 }
00102 }
00103
00104 DifferentialGeometry::DifferentialGeometry(const Point &P,
00105 const Vector &DPDU, const Vector &DPDV,
00106 const Vector &DNDU, const Vector &DNDV,
00107 float uu, float vv, const Shape *sh)
00108 : p(P), dpdu(DPDU), dpdv(DPDV), dndu((Normal)DNDU), dndv((Normal)DNDV) {
00109
00110 nn = Normal(Normalize(Cross(dpdu, dpdv)));
00111 u = uu;
00112 v = vv;
00113 shape = sh;
00114 dudx = dvdx = dudy = dvdy = 0;
00115
00116 if (shape->reverseOrientation ^ shape->transformSwapsHandedness)
00117 nn *= -1.f;
00118 }
00119
00120
00121 DifferentialGeometry::DifferentialGeometry(const Point &P,
00122 const Normal &NN,
00123 const Vector &DPDU, const Vector &DPDV,
00124 const Vector &DNDU, const Vector &DNDV,
00125 float uu, float vv, const Shape *sh)
00126 : p(P), nn(NN), dpdu(DPDU), dpdv(DPDV), dndu((Normal)DNDU), dndv((Normal)DNDV) {
00127
00128 u = uu;
00129 v = vv;
00130 shape = sh;
00131 dudx = dvdx = dudy = dvdy = 0;
00132 }
00133 void DifferentialGeometry::ComputeDifferentials(
00134 const RayDifferential &ray) const {
00135 if (ray.hasDifferentials) {
00136
00137
00138 float d = -Dot(nn, Vector(p.x, p.y, p.z));
00139 Vector rxv(ray.rx.o.x, ray.rx.o.y, ray.rx.o.z);
00140 float tx = -(Dot(nn, rxv) + d) / Dot(nn, ray.rx.d);
00141 Point px = ray.rx.o + tx * ray.rx.d;
00142 Vector ryv(ray.ry.o.x, ray.ry.o.y, ray.ry.o.z);
00143 float ty = -(Dot(nn, ryv) + d) / Dot(nn, ray.ry.d);
00144 Point py = ray.ry.o + ty * ray.ry.d;
00145 dpdx = px - p;
00146 dpdy = py - p;
00147
00148
00149 float A[2][2], Bx[2], By[2], x[2];
00150 int axes[2];
00151 if (fabsf(nn.x) > fabsf(nn.y) && fabsf(nn.x) > fabsf(nn.z)) {
00152 axes[0] = 1; axes[1] = 2;
00153 }
00154 else if (fabsf(nn.y) > fabsf(nn.z)) {
00155 axes[0] = 0; axes[1] = 2;
00156 }
00157 else {
00158 axes[0] = 0; axes[1] = 1;
00159 }
00160
00161 A[0][0] = dpdu[axes[0]];
00162 A[0][1] = dpdv[axes[0]];
00163 A[1][0] = dpdu[axes[1]];
00164 A[1][1] = dpdv[axes[1]];
00165 Bx[0] = px[axes[0]] - p[axes[0]];
00166 Bx[1] = px[axes[1]] - p[axes[1]];
00167 By[0] = py[axes[0]] - p[axes[0]];
00168 By[1] = py[axes[1]] - p[axes[1]];
00169 if (SolveLinearSystem2x2(A, Bx, x)) {
00170 dudx = x[0]; dvdx = x[1];
00171 }
00172 else {
00173 dudx = 1.; dvdx = 0.;
00174 }
00175 if (SolveLinearSystem2x2(A, By, x)) {
00176 dudy = x[0]; dvdy = x[1];
00177 }
00178 else {
00179 dudy = 0.; dvdy = 1.;
00180 }
00181 }
00182 else {
00183 dudx = dvdx = 0.;
00184 dudy = dvdy = 0.;
00185 dpdx = dpdy = Vector(0,0,0);
00186 }
00187 }