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 "primitive.h"
00025 #include "light.h"
00026 #include "material.h"
00027 #include "motionsystem.h"
00028
00029 using namespace lux;
00030
00031
00032 Primitive::~Primitive() { }
00033
00034 void Primitive::Refine(vector<boost::shared_ptr<Primitive> > &refined,
00035 const PrimitiveRefinementHints& refineHints, boost::shared_ptr<Primitive> thisPtr)
00036 {
00037 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Primitive::Refine method called!");
00038 }
00039
00040
00041 bool Primitive::Intersect(const Ray &r, Intersection *in) const {
00042 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Primitive::Intersect method called!");
00043 return false;
00044 }
00045 bool Primitive::IntersectP(const Ray &r) const {
00046 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Primitive::IntersectP method called!");
00047 return false;
00048 }
00049
00050
00051 void Primitive::GetShadingGeometry(const Transform &obj2world,
00052 const DifferentialGeometry &dg, DifferentialGeometry *dgShading) const
00053 {
00054 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Primitive::GetShadingGeometry method called!");
00055 }
00056
00057
00058 float Primitive::Area() const {
00059 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Primitive::Area method called!");
00060 return 0.f;
00061 }
00062 void Primitive::Sample(float u1, float u2, float u3, DifferentialGeometry *dg) const {
00063 luxError(LUX_BUG,LUX_SEVERE,"Unimplemented Primitive::Sample method called!");
00064 }
00065 float Primitive::Pdf(const Point &p) const {
00066 return 1.f / Area();
00067 }
00068 void Primitive::Sample(const Point &p,
00069 float u1, float u2, float u3, DifferentialGeometry *dg) const
00070 {
00071 Sample(u1, u2, u3, dg);
00072 }
00073 float Primitive::Pdf(const Point &p, const Vector &wi) const {
00074
00075 Intersection isect;
00076 Ray ray(p, wi);
00077 if (!Intersect(ray, &isect)) return 0.f;
00078
00079 float pdf = DistanceSquared(p, ray(ray.maxt)) /
00080 (AbsDot(isect.dg.nn, -wi) * Area());
00081 if (AbsDot(isect.dg.nn, -wi) == 0.f) pdf = INFINITY;
00082 return pdf;
00083 }
00084 float Primitive::Pdf(const Point &p, const Point &po) const {
00085 return 1.f / Area();
00086 }
00087
00088
00089 BSDF *Intersection::GetBSDF(const TsPack *tspack, const RayDifferential &ray)
00090 const {
00091
00092
00093 dg.ComputeDifferentials(ray);
00094 DifferentialGeometry dgShading;
00095 primitive->GetShadingGeometry(WorldToObject.GetInverse(), dg, &dgShading);
00096 return material->GetBSDF(tspack, dg, dgShading);
00097 }
00098 SWCSpectrum Intersection::Le(const TsPack *tspack, const Vector &w) const {
00099 return arealight ? arealight->L(tspack, dg, w) : SWCSpectrum(0.);
00100 }
00101 SWCSpectrum Intersection::Le(const TsPack *tspack, const Ray &ray, const Normal &n, BSDF **bsdf, float *pdf, float *pdfDirect) const
00102 {
00103 if (arealight)
00104 return arealight->L(tspack, ray, dg, n, bsdf, pdf, pdfDirect);
00105 *pdf = *pdfDirect = 0.f;
00106 *bsdf = NULL;
00107 return 0.f;
00108 }
00109
00110
00111 AreaLightPrimitive::AreaLightPrimitive(boost::shared_ptr<Primitive> aPrim,
00112 AreaLight* aAreaLight)
00113 {
00114 this->prim = aPrim;
00115 this->areaLight = aAreaLight;
00116 }
00117 void AreaLightPrimitive::Refine(vector<boost::shared_ptr<Primitive> > &refined,
00118 const PrimitiveRefinementHints& refineHints,
00119 boost::shared_ptr<Primitive> thisPtr)
00120 {
00121
00122 vector<boost::shared_ptr<Primitive> > tmpRefined;
00123 prim->Refine(tmpRefined, refineHints, prim);
00124 for(u_int i=0; i<tmpRefined.size(); i++) {
00125 boost::shared_ptr<Primitive> currPrim(
00126 new AreaLightPrimitive(tmpRefined[i], areaLight));
00127 refined.push_back(currPrim);
00128 }
00129 }
00130 bool AreaLightPrimitive::Intersect(const Ray &r, Intersection *in) const {
00131 if(!prim->Intersect(r, in))
00132 return false;
00133 in->arealight = areaLight;
00134 return true;
00135 }
00136
00137
00138 bool InstancePrimitive::Intersect(const Ray &r,
00139 Intersection *isect) const {
00140 Ray ray = WorldToInstance(r);
00141 if (!instance->Intersect(ray, isect))
00142 return false;
00143 r.maxt = ray.maxt;
00144 isect->WorldToObject = isect->WorldToObject * WorldToInstance;
00145
00146 isect->dg.p = InstanceToWorld(isect->dg.p);
00147 isect->dg.nn = Normalize(InstanceToWorld(isect->dg.nn));
00148 isect->dg.dpdu = InstanceToWorld(isect->dg.dpdu);
00149 isect->dg.dpdv = InstanceToWorld(isect->dg.dpdv);
00150 isect->dg.dndu = InstanceToWorld(isect->dg.dndu);
00151 isect->dg.dndv = InstanceToWorld(isect->dg.dndv);
00152 isect->dg.handle = isect->primitive;
00153 isect->primitive = this;
00154 if(material)
00155 isect->material = material.get();
00156 return true;
00157 }
00158 bool InstancePrimitive::IntersectP(const Ray &r) const {
00159 return instance->IntersectP(WorldToInstance(r));
00160 }
00161 void InstancePrimitive::GetShadingGeometry(const Transform &obj2world,
00162 const DifferentialGeometry &dg, DifferentialGeometry *dgShading) const
00163 {
00164 Transform o2w(WorldToInstance * obj2world);
00165
00166 DifferentialGeometry dgl(WorldToInstance(dg.p),
00167 Normalize(WorldToInstance(dg.nn)),
00168 WorldToInstance(dg.dpdu), WorldToInstance(dg.dpdv),
00169 WorldToInstance(dg.dndu), WorldToInstance(dg.dndv),
00170 dg.u, dg.v, dg.handle);
00171 memcpy(dgl.triangleBaryCoords, dg.triangleBaryCoords, 3 * sizeof(float));
00172 reinterpret_cast<const Primitive *>(dg.handle)->GetShadingGeometry(o2w, dgl, dgShading);
00173 dgShading->p = InstanceToWorld(dgShading->p);
00174 dgShading->nn = Normalize(InstanceToWorld(dgShading->nn));
00175 dgShading->dpdu = InstanceToWorld(dgShading->dpdu);
00176 dgShading->dpdv = InstanceToWorld(dgShading->dpdv);
00177 dgShading->dndu = InstanceToWorld(dgShading->dndu);
00178 dgShading->dndv = InstanceToWorld(dgShading->dndv);
00179 dgShading->dpdx = InstanceToWorld(dgShading->dpdx);
00180 dgShading->dpdy = InstanceToWorld(dgShading->dpdy);
00181 }
00182
00183
00184 bool MotionPrimitive::Intersect(const Ray &r,
00185 Intersection *isect) const {
00186
00187 Transform InstanceToWorld = motionSystem->Sample(r.time);
00188 Transform WorldToInstance = InstanceToWorld.GetInverse();
00189
00190 Ray ray = WorldToInstance(r);
00191 if (!instance->Intersect(ray, isect))
00192 return false;
00193 r.maxt = ray.maxt;
00194 isect->WorldToObject = isect->WorldToObject * WorldToInstance;
00195
00196 isect->dg.p = InstanceToWorld(isect->dg.p);
00197 isect->dg.nn = Normalize(InstanceToWorld(isect->dg.nn));
00198 isect->dg.dpdu = InstanceToWorld(isect->dg.dpdu);
00199 isect->dg.dpdv = InstanceToWorld(isect->dg.dpdv);
00200 isect->dg.dndu = InstanceToWorld(isect->dg.dndu);
00201 isect->dg.dndv = InstanceToWorld(isect->dg.dndv);
00202 isect->dg.handle = isect->primitive;
00203 isect->primitive = this;
00204 isect->dg.time = r.time;
00205 return true;
00206 }
00207
00208 bool MotionPrimitive::IntersectP(const Ray &r) const {
00209 Transform InstanceToWorld = motionSystem->Sample(r.time);
00210 Transform WorldToInstance = InstanceToWorld.GetInverse();
00211
00212 return instance->IntersectP(WorldToInstance(r));
00213 }
00214 void MotionPrimitive::GetShadingGeometry(const Transform &obj2world,
00215 const DifferentialGeometry &dg, DifferentialGeometry *dgShading) const
00216 {
00217 Transform InstanceToWorld = motionSystem->Sample(dg.time);
00218 Transform WorldToInstance = InstanceToWorld.GetInverse();
00219 Transform o2w(WorldToInstance * obj2world);
00220
00221 DifferentialGeometry dgl(WorldToInstance(dg.p),
00222 Normalize(WorldToInstance(dg.nn)),
00223 WorldToInstance(dg.dpdu), WorldToInstance(dg.dpdv),
00224 WorldToInstance(dg.dndu), WorldToInstance(dg.dndv),
00225 dg.u, dg.v, dg.handle);
00226 memcpy(dgl.triangleBaryCoords, dg.triangleBaryCoords, 3 * sizeof(float));
00227 reinterpret_cast<const Primitive *>(dg.handle)->GetShadingGeometry(o2w, dgl, dgShading);
00228 dgShading->p = InstanceToWorld(dgShading->p);
00229 dgShading->nn = Normalize(InstanceToWorld(dgShading->nn));
00230 dgShading->dpdu = InstanceToWorld(dgShading->dpdu);
00231 dgShading->dpdv = InstanceToWorld(dgShading->dpdv);
00232 dgShading->dndu = InstanceToWorld(dgShading->dndu);
00233 dgShading->dndv = InstanceToWorld(dgShading->dndv);
00234 dgShading->dpdx = InstanceToWorld(dgShading->dpdx);
00235 dgShading->dpdy = InstanceToWorld(dgShading->dpdy);
00236 }
00237
00238 BBox MotionPrimitive::WorldBound() const {
00239 return motionSystem->Bound(instance->WorldBound());
00240 }
00241