diff --git a/include/mitsuba/render/shape.h b/include/mitsuba/render/shape.h
index 3c7fe7ea..8ad7e0a3 100644
--- a/include/mitsuba/render/shape.h
+++ b/include/mitsuba/render/shape.h
@@ -166,6 +166,7 @@ public:
/** \brief Abstract base class of all shapes
* \ingroup librender
+ * \ingroup libpython
*/
class MTS_EXPORT_RENDER Shape : public ConfigurableObject {
public:
@@ -235,6 +236,10 @@ public:
* intersection. The function \ref fillIntersectionRecord()
* can later use this information to fill in a detailed
* intersection record.
+ *
+ * \remark In Python, this function also calls \c fillIntersectionRecord
+ * and has the signature
+ * intersection = shape.rayIntersect(ray, mint, maxt)
*/
virtual bool rayIntersect(const Ray &ray, Float mint,
Float maxt, Float &t, void *temp) const;
@@ -248,12 +253,17 @@ public:
* shapes, this will simply call forward the call to \ref
* rayIntersect. When the shape actually contains a nested
* kd-tree, some optimizations are possible.
+ *
+ * \remark This function is not exposed in Python
*/
virtual bool rayIntersect(const Ray &ray, Float mint, Float maxt) const;
/**
* \brief Given that an intersection has been found, create a
* detailed intersection record
+ *
+ * \remark This function is not directly exposed in Python.
+ * It is implicitly called as part of \c rayIntersect.
*/
virtual void fillIntersectionRecord(const Ray &ray,
const void *temp, Intersection &its) const;
@@ -276,6 +286,9 @@ public:
* \param shadingFrame
* Specifies whether to compute the derivative of the
* geometric normal \a or the shading normal of the surface
+ *
+ * \remark In Python, the signature of this function is
+ * dndu, dndv = shape.getNormalDerivative(its, shadingFrame)
*/
virtual void getNormalDerivative(const Intersection &its,
Vector &dndu, Vector &dndv, bool shadingFrame = true) const;
@@ -293,6 +306,9 @@ public:
* \param shadingFrame
* Specifies whether to compute the curvature based on the
* geometric normal \a or the shading normal of the surface
+ *
+ * \remark In Python, the signature of this function is
+ * H, K = shape.getCurvature(its, shadingFrame)
*/
void getCurvature(const Intersection &its, Float &H, Float &K,
bool shadingFrame = true) const;
@@ -303,6 +319,8 @@ public:
* This function is used by the kd-tree visualization in
* the interactive walkthrough. The default implementation
* simply returns NULL.
+ *
+ * \remark This function is not exposed in Python
*/
virtual const KDTreeBase *getKDTree() const;
diff --git a/src/libpython/core.cpp b/src/libpython/core.cpp
index ac625321..247afd60 100644
--- a/src/libpython/core.cpp
+++ b/src/libpython/core.cpp
@@ -20,6 +20,13 @@
#include
#include
+#if defined(__LINUX__)
+# if !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+# endif
+# include
+#endif
+
using namespace mitsuba;
void initializeFramework() {
@@ -28,12 +35,26 @@ void initializeFramework() {
Object::staticInitialization();
PluginManager::staticInitialization();
Statistics::staticInitialization();
+ FileStream::staticInitialization();
Thread::staticInitialization();
Logger::staticInitialization();
Spectrum::staticInitialization();
+ Bitmap::staticInitialization();
Scheduler::staticInitialization();
SHVector::staticInitialization();
SceneHandler::staticInitialization();
+
+ fs::path sharedLibraryPath;
+
+ /* Try to detect the python plugin path */
+ #if defined(__LINUX__)
+ Dl_info info;
+ dladdr((void *) &initializeFramework, &info);
+ if (info.dli_fname)
+ sharedLibraryPath = fs::path(info.dli_fname);
+ #elif defined(__OSX__)
+
+ #endif
}
void shutdownFramework() {
@@ -41,9 +62,11 @@ void shutdownFramework() {
SceneHandler::staticShutdown();
SHVector::staticShutdown();
Scheduler::staticShutdown();
+ Bitmap::staticShutdown();
Spectrum::staticShutdown();
Logger::staticShutdown();
Thread::staticShutdown();
+ FileStream::staticShutdown();
Statistics::staticShutdown();
PluginManager::staticShutdown();
Object::staticShutdown();
@@ -316,6 +339,7 @@ bp::object cast(ConfigurableObject *obj) {
#define TryCast(ClassName) if (cls->derivesFrom(MTS_CLASS(ClassName))) \
return bp::object(ref(static_cast(obj)))
TryCast(BSDF);
+ TryCast(TriMesh);
TryCast(Shape);
TryCast(PhaseFunction);
TryCast(Integrator);
@@ -1207,12 +1231,14 @@ void export_core() {
/* Functions from qmc.h */
bp::def("radicalInverse2Single", radicalInverse2Single);
bp::def("radicalInverse2Double", radicalInverse2Double);
+ bp::def("radicalInverse2", radicalInverse2Double);
bp::def("sobol2Single", sobol2Single);
bp::def("sobol2Double", sobol2Double);
- bp::def("sampleTEA", sobol2Double);
- bp::def("radicalInverse", sobol2Double);
- bp::def("radicalInverseFast", sobol2Double);
- bp::def("radicalInverseIncremental", sobol2Double);
+ bp::def("sobol2", sobol2Double);
+ bp::def("sampleTEA", sampleTEA);
+ bp::def("radicalInverse", radicalInverse);
+ bp::def("radicalInverseFast", radicalInverseFast);
+ bp::def("radicalInverseIncremental", radicalInverseIncremental);
bp::detail::current_scope = oldScope;
}
diff --git a/src/libpython/render.cpp b/src/libpython/render.cpp
index 9ce5c597..8079405b 100644
--- a/src/libpython/render.cpp
+++ b/src/libpython/render.cpp
@@ -30,6 +30,34 @@ bp::tuple bsdf_sample(const BSDF *bsdf, BSDFSamplingRecord &bRec, const Point2 &
return bp::make_tuple(result, pdf);
}
+bp::object shape_rayIntersect(const Shape *shape, const Ray &ray, Float mint, Float maxt) {
+ uint8_t temp[MTS_KD_INTERSECTION_TEMP];
+ Float t;
+
+ if (!shape->rayIntersect(ray, mint, maxt, t, temp))
+ return bp::object();
+
+ Intersection its;
+ its.shape = shape;
+ its.t = t;
+ shape->fillIntersectionRecord(ray, temp, its);
+
+ return bp::object(its);
+}
+
+bp::tuple shape_getCurvature(const Shape *shape, const Intersection &its, bool shadingFrame) {
+ Float H, K;
+ shape->getCurvature(its, H, K, shadingFrame);
+ return bp::make_tuple(H, K);
+}
+
+bp::tuple shape_getNormalDerivative(const Shape *shape, const Intersection &its, bool shadingFrame) {
+ Vector dpdu, dpdv;
+ shape->getNormalDerivative(its, dpdu, dpdv, shadingFrame);
+ return bp::make_tuple(dpdu, dpdv);
+}
+
+
ref loadScene(const fs::path &filename, const StringMap ¶ms) {
SceneHandler::ParameterMap pmap;
for (StringMap::const_iterator it = params.begin(); it != params.end(); ++it)
@@ -133,6 +161,7 @@ void export_render() {
.def_readwrite("color", &Intersection::color)
.def_readwrite("wi", &Intersection::wi)
.def_readwrite("shape", &Intersection::shape)
+ .def_readwrite("instance", &Intersection::instance)
.add_property("hasUVPartials", &intersection_get_hasUVPartials, &intersection_set_hasUVPartials)
.add_property("primIndex", &intersection_get_primIndex, &intersection_set_primIndex)
.def("toWorld", &Intersection::toWorld, BP_RETURN_VALUE)
@@ -146,6 +175,42 @@ void export_render() {
.def("LoSub", &Intersection::LoSub)
.def("__repr__", &Intersection::toString);
+ Medium *(Shape::*shape_getInteriorMedium)(void) = &Shape::getInteriorMedium;
+ Medium *(Shape::*shape_getExteriorMedium)(void) = &Shape::getExteriorMedium;
+ Sensor *(Shape::*shape_getSensor)(void) = &Shape::getSensor;
+ Emitter *(Shape::*shape_getEmitter)(void) = &Shape::getEmitter;
+ Subsurface *(Shape::*shape_getSubsurface)(void) = &Shape::getSubsurface;
+ BSDF *(Shape::*shape_getBSDF)(void) = &Shape::getBSDF;
+
+ BP_CLASS(Shape, ConfigurableObject, bp::no_init)
+ .def("getName", &Shape::getName, BP_RETURN_VALUE)
+ .def("isCompound", &Shape::isCompound)
+ .def("getElement", &Shape::getElement, BP_RETURN_VALUE)
+ .def("getSurfaceArea", &Shape::getSurfaceArea)
+ .def("getAABB", &Shape::getAABB, BP_RETURN_VALUE)
+ .def("getClippedAABB", &Shape::getClippedAABB, BP_RETURN_VALUE)
+ .def("createTriMesh", &Shape::createTriMesh, BP_RETURN_VALUE)
+ .def("rayIntersect", &shape_rayIntersect)
+ .def("getNormalDerivative", &shape_getNormalDerivative)
+ .def("getCurvature", &shape_getCurvature)
+ .def("samplePosition", &Shape::samplePosition)
+ .def("pdfPosition", &Shape::pdfPosition)
+ .def("sampleDirect", &Shape::sampleDirect)
+ .def("pdfDirect", &Shape::pdfDirect)
+ .def("getInteriorMedium", shape_getInteriorMedium, BP_RETURN_VALUE)
+ .def("getExteriorMedium", shape_getExteriorMedium, BP_RETURN_VALUE)
+ .def("isMediumTransition", &Shape::isMediumTransition)
+ .def("hasSubsurface", &Shape::hasSubsurface)
+ .def("getSubsurface", shape_getSubsurface, BP_RETURN_VALUE)
+ .def("isEmitter", &Shape::isEmitter)
+ .def("getEmitter", shape_getEmitter, BP_RETURN_VALUE)
+ .def("isSensor", &Shape::isSensor)
+ .def("getSensor", shape_getSensor, BP_RETURN_VALUE)
+ .def("hasBSDF", &Shape::hasBSDF)
+ .def("getBSDF", shape_getBSDF, BP_RETURN_VALUE)
+ .def("getPrimitiveCount", &Shape::getPrimitiveCount)
+ .def("getEffectivePrimitiveCount", &Shape::getEffectivePrimitiveCount);
+
BP_STRUCT(BSDFSamplingRecord, (bp::init()))
.def(bp::init())
.def(bp::init())
@@ -217,8 +282,8 @@ void export_render() {
bp::class_("Noise")
.def("perlinNoise", &Noise::perlinNoise)
- .def("fbm", &Noise::fbm)
- .def("turbulence", &Noise::turbulence);
+ .def("turbulence", &Noise::turbulence)
+ .def("fbm", &Noise::fbm);
bp::detail::current_scope = oldScope;
}