diff --git a/include/mitsuba/render/kdtree.h b/include/mitsuba/render/kdtree.h index a7004a5e..3dfbf9e5 100644 --- a/include/mitsuba/render/kdtree.h +++ b/include/mitsuba/render/kdtree.h @@ -270,6 +270,90 @@ protected: }; #endif + /** + * \brief After having found a unique intersection, fill a proper record + * using the temporary information collected in \ref intersect() + */ + template FINLINE void fillIntersectionRecord(const Ray &ray, + const void *temp, Intersection &its) const { + const IntersectionCache *cache = reinterpret_cast(temp); + const Shape *shape = m_shapes[cache->shapeIndex]; + if (m_triangleFlag[cache->shapeIndex]) { + const TriMesh *trimesh = static_cast(shape); + const Triangle &tri = trimesh->getTriangles()[cache->primIndex]; + const Point *vertexPositions = trimesh->getVertexPositions(); + const Normal *vertexNormals = trimesh->getVertexNormals(); + const Point2 *vertexTexcoords = trimesh->getVertexTexcoords(); + const Spectrum *vertexColors = trimesh->getVertexColors(); + const TangentSpace *vertexTangents = trimesh->getVertexTangents(); + const Vector b(1 - cache->u - cache->v, cache->u, cache->v); + + const uint32_t idx0 = tri.idx[0], idx1 = tri.idx[1], idx2 = tri.idx[2]; + const Point &p0 = vertexPositions[idx0]; + const Point &p1 = vertexPositions[idx1]; + const Point &p2 = vertexPositions[idx2]; + + if (BarycentricPos) + its.p = p0 * b.x + p1 * b.y + p2 * b.z; + else + its.p = ray(its.t); + + Normal faceNormal(cross(p1-p0, p2-p0)); + Float length = faceNormal.length(); + if (!faceNormal.isZero()) + faceNormal /= length; + + its.geoFrame = Frame(faceNormal); + + if (EXPECT_TAKEN(vertexNormals)) { + const Normal &n0 = vertexNormals[idx0]; + const Normal &n1 = vertexNormals[idx1]; + const Normal &n2 = vertexNormals[idx2]; + + if (EXPECT_TAKEN(!vertexTangents)) { + its.shFrame = Frame(normalize(n0 * b.x + n1 * b.y + n2 * b.z)); + } else { + const TangentSpace &t0 = vertexTangents[idx0]; + const TangentSpace &t1 = vertexTangents[idx1]; + const TangentSpace &t2 = vertexTangents[idx2]; + const Vector dpdu = t0.dpdu * b.x + t1.dpdu * b.y + t2.dpdu * b.z; + its.shFrame.n = normalize(n0 * b.x + n1 * b.y + n2 * b.z); + its.shFrame.s = normalize(dpdu - its.shFrame.n + * dot(its.shFrame.n, dpdu)); + its.shFrame.t = cross(its.shFrame.n, its.shFrame.s); + its.dpdu = dpdu; + its.dpdv = t0.dpdv * b.x + t1.dpdv * b.y + t2.dpdv * b.z; + } + } else { + its.shFrame = its.geoFrame; + } + + if (EXPECT_TAKEN(vertexTexcoords)) { + const Point2 &t0 = vertexTexcoords[idx0]; + const Point2 &t1 = vertexTexcoords[idx1]; + const Point2 &t2 = vertexTexcoords[idx2]; + its.uv = t0 * b.x + t1 * b.y + t2 * b.z; + } else { + its.uv = Point2(0.0f); + } + + if (EXPECT_NOT_TAKEN(vertexColors)) { + const Spectrum &c0 = vertexColors[idx0], + &c1 = vertexColors[idx1], + &c2 = vertexColors[idx2]; + its.color = c0 * b.x + c1 * b.y + c2 * b.z; + } + + its.wi = its.toLocal(-ray.d); + its.shape = trimesh; + its.hasUVPartials = false; + } else { + shape->fillIntersectionRecord(ray, + reinterpret_cast(temp) + 8, its); + } + } + + /// Virtual destructor virtual ~KDTree(); private: diff --git a/include/mitsuba/render/shape.h b/include/mitsuba/render/shape.h index 86f40fc9..4edc19fe 100644 --- a/include/mitsuba/render/shape.h +++ b/include/mitsuba/render/shape.h @@ -206,7 +206,7 @@ public: * \brief Given that an intersection has been found, create a * detailed intersection record */ - virtual void fillIntersectionRecord(const Ray &ray, Float t, + virtual void fillIntersectionRecord(const Ray &ray, const void *temp, Intersection &its) const; /** diff --git a/setpath.sh b/setpath.sh index f20f30e9..9ed4cfa7 100755 --- a/setpath.sh +++ b/setpath.sh @@ -5,4 +5,5 @@ if [[ "$unamestr" == 'Darwin' ]]; then else export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`/src/libcore:`pwd`/src/librender:`pwd`/src/libhw export PATH=`pwd`:$PATH + ulimit -c 1000000000 fi diff --git a/src/librender/kdtree.cpp b/src/librender/kdtree.cpp index 56215767..55773dba 100644 --- a/src/librender/kdtree.cpp +++ b/src/librender/kdtree.cpp @@ -121,82 +121,8 @@ bool KDTree::rayIntersect(const Ray &ray, Intersection &its) const { if (EXPECT_TAKEN(maxt > mint)) { if (rayIntersectHavran(ray, mint, maxt, its.t, temp)) { - /* After having found a unique intersection, fill a proper record - using the temporary information collected in \ref intersect() */ - const IntersectionCache *cache = reinterpret_cast(temp); - const Shape *shape = m_shapes[cache->shapeIndex]; - if (m_triangleFlag[cache->shapeIndex]) { - const TriMesh *trimesh = static_cast(shape); - const Triangle &tri = trimesh->getTriangles()[cache->primIndex]; - const Point *vertexPositions = trimesh->getVertexPositions(); - const Normal *vertexNormals = trimesh->getVertexNormals(); - const Point2 *vertexTexcoords = trimesh->getVertexTexcoords(); - const Spectrum *vertexColors = trimesh->getVertexColors(); - const TangentSpace *vertexTangents = trimesh->getVertexTangents(); - const Vector b(1 - cache->u - cache->v, cache->u, cache->v); - - const uint32_t idx0 = tri.idx[0], idx1 = tri.idx[1], idx2 = tri.idx[2]; - const Point &p0 = vertexPositions[idx0]; - const Point &p1 = vertexPositions[idx1]; - const Point &p2 = vertexPositions[idx2]; - - //its.p = ray(its.t); - its.p = p0 * b.x + p1 * b.y + p2 * b.z; - Normal faceNormal(cross(p1-p0, p2-p0)); - Float length = faceNormal.length(); - if (!faceNormal.isZero()) - faceNormal /= length; - - its.geoFrame = Frame(faceNormal); - - if (EXPECT_TAKEN(vertexNormals)) { - const Normal &n0 = vertexNormals[idx0]; - const Normal &n1 = vertexNormals[idx1]; - const Normal &n2 = vertexNormals[idx2]; - - if (EXPECT_TAKEN(!vertexTangents)) { - its.shFrame = Frame(normalize(n0 * b.x + n1 * b.y + n2 * b.z)); - } else { - const TangentSpace &t0 = vertexTangents[idx0]; - const TangentSpace &t1 = vertexTangents[idx1]; - const TangentSpace &t2 = vertexTangents[idx2]; - const Vector dpdu = t0.dpdu * b.x + t1.dpdu * b.y + t2.dpdu * b.z; - its.shFrame.n = normalize(n0 * b.x + n1 * b.y + n2 * b.z); - its.shFrame.s = normalize(dpdu - its.shFrame.n - * dot(its.shFrame.n, dpdu)); - its.shFrame.t = cross(its.shFrame.n, its.shFrame.s); - its.dpdu = dpdu; - its.dpdv = t0.dpdv * b.x + t1.dpdv * b.y + t2.dpdv * b.z; - } - } else { - its.shFrame = its.geoFrame; - } - - if (EXPECT_TAKEN(vertexTexcoords)) { - const Point2 &t0 = vertexTexcoords[idx0]; - const Point2 &t1 = vertexTexcoords[idx1]; - const Point2 &t2 = vertexTexcoords[idx2]; - its.uv = t0 * b.x + t1 * b.y + t2 * b.z; - } else { - its.uv = Point2(0.0f); - } - - if (EXPECT_NOT_TAKEN(vertexColors)) { - const Spectrum &c0 = vertexColors[idx0], - &c1 = vertexColors[idx1], - &c2 = vertexColors[idx2]; - its.color = c0 * b.x + c1 * b.y + c2 * b.z; - } - - its.wi = its.toLocal(-ray.d); - its.shape = trimesh; - its.hasUVPartials = false; - return true; - } else { - shape->fillIntersectionRecord(ray, its.t, - reinterpret_cast(temp) + 8, its); - return true; - } + fillIntersectionRecord(ray, temp, its); + return true; } } } diff --git a/src/librender/preview.cpp b/src/librender/preview.cpp index 61baa91f..33fe08a5 100644 --- a/src/librender/preview.cpp +++ b/src/librender/preview.cpp @@ -348,8 +348,8 @@ void PreviewWorker::processCoherent(const WorkUnit *workUnit, WorkResult *workRe Point(primRay4.o[0].f[idx], primRay4.o[1].f[idx], primRay4.o[2].f[idx]), Vector(primRay4.d[0].f[idx], primRay4.d[1].f[idx], primRay4.d[2].f[idx]) ); - shape->fillIntersectionRecord(ray, its4.t.f[idx], temp + - + idx * MTS_KD_INTERSECTION_TEMP + 8, its); + its.t = its4.t.f[idx]; + shape->fillIntersectionRecord(ray, temp + idx * MTS_KD_INTERSECTION_TEMP + 8, its); } wo.x = nSecD[0].f[idx]; wo.y = nSecD[1].f[idx]; wo.z = nSecD[2].f[idx]; diff --git a/src/librender/shape.cpp b/src/librender/shape.cpp index 60105f1b..2f15abfc 100644 --- a/src/librender/shape.cpp +++ b/src/librender/shape.cpp @@ -127,7 +127,7 @@ bool Shape::rayIntersect(const Ray &ray, Float mint, } -void Shape::fillIntersectionRecord(const Ray &ray, Float t, +void Shape::fillIntersectionRecord(const Ray &ray, const void *temp, Intersection &its) const { Log(EError, "%s::fillIntersectionRecord(): Not implemented!", getClass()->getName().c_str()); diff --git a/src/shapes/cylinder.cpp b/src/shapes/cylinder.cpp index d2fe0cdc..204b0483 100644 --- a/src/shapes/cylinder.cpp +++ b/src/shapes/cylinder.cpp @@ -151,9 +151,9 @@ public: } } - void fillIntersectionRecord(const Ray &ray, Float t, + void fillIntersectionRecord(const Ray &ray, const void *temp, Intersection &its) const { - its.p = ray(t); + its.p = ray(its.t); Point local = m_worldToObject(its.p); Float phi = std::atan2(local.y, local.x); diff --git a/src/shapes/hair.cpp b/src/shapes/hair.cpp index bfa89597..989c8043 100644 --- a/src/shapes/hair.cpp +++ b/src/shapes/hair.cpp @@ -612,9 +612,9 @@ public: return m_kdtree->rayIntersect(ray, mint, maxt); } - void fillIntersectionRecord(const Ray &ray, Float t, + void fillIntersectionRecord(const Ray &ray, const void *temp, Intersection &its) const { - its.p = ray(t); + its.p = ray(its.t); /* No UV coordinates for now */ its.uv = Point2(0,0); diff --git a/src/shapes/instance.cpp b/src/shapes/instance.cpp index ad63f45b..620ab77e 100644 --- a/src/shapes/instance.cpp +++ b/src/shapes/instance.cpp @@ -107,10 +107,17 @@ public: return false; } - void fillIntersectionRecord(const Ray &ray, Float t, + void fillIntersectionRecord(const Ray &ray, const void *temp, Intersection &its) const { const KDTree *kdtree = m_shapeGroup->getKDTree(); - Log(EError, "fillIntersectionRecord(): Unsupported!"); + kdtree->fillIntersectionRecord(ray, temp, its); + its.shFrame.n = normalize(m_objectToWorld(its.shFrame.n)); + its.shFrame.s = normalize(m_objectToWorld(its.shFrame.s)); + its.shFrame.t = normalize(m_objectToWorld(its.shFrame.t)); + its.geoFrame = Frame(normalize(m_objectToWorld(its.geoFrame.n))); + its.wi = its.shFrame.toLocal(-ray.d); + its.dpdu = m_objectToWorld(its.dpdu); + its.dpdv = m_objectToWorld(its.dpdv); } MTS_DECLARE_CLASS() diff --git a/src/shapes/shapegroup.cpp b/src/shapes/shapegroup.cpp index 2fe50646..066cd904 100644 --- a/src/shapes/shapegroup.cpp +++ b/src/shapes/shapegroup.cpp @@ -60,6 +60,10 @@ void ShapeGroup::addChild(const std::string &name, ConfigurableObject *child) { Log(EError, "Nested instancing is not supported!"); } else if (cClass->derivesFrom(Shape::m_theClass)) { Shape *shape = static_cast(child); + if (shape->isLuminaire()) + Log(EError, "Instancing of luminaires is not supported"); + if (shape->hasSubsurface()) + Log(EError, "Instancing of subsurface integrators is not supported"); if (shape->isCompound()) { int index = 0; do { diff --git a/src/shapes/sphere.cpp b/src/shapes/sphere.cpp index ed2bd37d..a0478d5f 100644 --- a/src/shapes/sphere.cpp +++ b/src/shapes/sphere.cpp @@ -130,10 +130,9 @@ public: return true; } - void fillIntersectionRecord(const Ray &ray, Float t, + void fillIntersectionRecord(const Ray &ray, const void *temp, Intersection &its) const { - its.t = t; - its.p = ray(t); + its.p = ray(its.t); Vector local = m_worldToObject(its.p - m_center); Float theta = std::acos(std::min(std::max(local.z/m_radius, -(Float) 1), (Float) 1)); diff --git a/tools/blender/mitsuba/properties/lamp.py b/tools/blender/mitsuba/properties/lamp.py index acede349..f5860af7 100644 --- a/tools/blender/mitsuba/properties/lamp.py +++ b/tools/blender/mitsuba/properties/lamp.py @@ -50,7 +50,7 @@ class mitsuba_lamp(declarative_property_group): 'type': 'float', 'attr': 'sampling_weight', 'name': 'Sampling weight', - 'description': 'Determines the relative amount of samples for this light source', + 'description': 'Relative amount of samples to place on this light source (e.g. the "importance")', 'default': 1.0, 'min': 1e-3, 'soft_min': 1e-3,