diff --git a/data/blender/mitsuba/core/__init__.py b/data/blender/mitsuba/core/__init__.py index 95cd21e0..7909d213 100644 --- a/data/blender/mitsuba/core/__init__.py +++ b/data/blender/mitsuba/core/__init__.py @@ -148,7 +148,7 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base): adj.exportMaterial(pm) adj.exportPreviewMesh(pm) adj.writeFooter() - (mts_path, tail) = os.path.split(bpy.path.abspath(scene.mitsuba_engine.binary_path)) + mts_path = scene.mitsuba_engine.binary_path mitsuba_binary = os.path.join(mts_path, "mitsuba") env = copy.copy(os.environ) mts_render_libpath = os.path.join(mts_path, "src/librender") @@ -238,7 +238,7 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base): return if scene.mitsuba_engine.export_mode == 'render': - (mts_path, tail) = os.path.split(bpy.path.abspath(scene.mitsuba_engine.binary_path)) + mts_path = scene.mitsuba_engine.binary_path mtsgui_binary = os.path.join(mts_path, "mtsgui") mitsuba_binary = os.path.join(mts_path, "mitsuba") env = copy.copy(os.environ) diff --git a/data/blender/mitsuba/operators/__init__.py b/data/blender/mitsuba/operators/__init__.py index 616e7728..4f9f82f1 100644 --- a/data/blender/mitsuba/operators/__init__.py +++ b/data/blender/mitsuba/operators/__init__.py @@ -171,7 +171,7 @@ class EXPORT_OT_mitsuba(bpy.types.Operator): self.report({'ERROR'}, 'Mitsuba binary path must be specified!') return {'CANCELLED'} - (mts_path, tail) = os.path.split(bpy.path.abspath(scene.mitsuba_engine.binary_path)) + mts_path = scene.mitsuba_engine.binary_path mtsimport_binary = os.path.join(mts_path, "mtsimport") env = copy.copy(os.environ) mts_render_libpath = os.path.join(mts_path, "src/librender") diff --git a/data/blender/mitsuba/render.py b/data/blender/mitsuba/render.py deleted file mode 100644 index 46863920..00000000 --- a/data/blender/mitsuba/render.py +++ /dev/null @@ -1,228 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -import bpy - -class MitsubaCheckOp(bpy.types.Operator): - bl_idname = 'mts.check' - bl_label = 'Check scene' - - def reportWarning(self, msg): - self.report({'WARNING'}, msg) - print("MtsBlend: %s" % msg) - - def _check_lamp(self, lamp): - hasErrors = False - if lamp.type == 'POINT' and lamp.falloff_type != 'INVERSE_SQUARE': - self.reportWarning('Point light "%s" needs to have inverse square falloff' % lamp.name) - hasErrors = True - - if hasErrors: - self.reportWarning('Encountered one or more problems -- check the console') - else: - self.report({'INFO'}, "No problems found") - - def execute(self, context): - scene = bpy.data.scenes[0] - for obj in scene.objects: - if obj.type == 'LAMP': - self._check_lamp(obj.data) - return {'FINISHED'} - -# Basic Mitsuba integration based on the POV-Ray add-on -# Piggybacks on the COLLADA exporter to get most things done -class MitsubaRender(bpy.types.RenderEngine): - bl_idname = 'MITSUBA_RENDER' - bl_label = "Mitsuba" - - def _export_worldtrafo(self, adjfile, trafo): - adjfile.write('\t\t\n') - adjfile.write('\t\t\t\n\t\t\n') - - - def _export_lamp(self, adjfile, lamp, idx): - if lamp.data.type == 'POINT': - adjfile.write('\t\n' % lamp.data.name) - mult = lamp.data.energy * lamp.data.distance * lamp.data.distance / 2 - self._export_worldtrafo(adjfile, lamp.matrix_world) - adjfile.write('\t\t\n' - % (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)) - adjfile.write('\t\n') - elif lamp.data.type == 'AREA': - adjfile.write('\t\n') - size_x = lamp.data.size - size_y = lamp.data.size - if lamp.data.shape == 'RECTANGLE': - size_y = lamp.data.size_y - path = os.path.join(os.path.join(self._temp_dir, 'meshes'), "_area_luminaire_%d.obj" % idx) - - adjfile.write('\t\t\n' % path) - self._export_worldtrafo(adjfile, lamp.matrix_world) - - adjfile.write('\n\t\t\n' % lamp.data.name) - mult = lamp.data.energy * lamp.data.distance * lamp.data.distance / (size_x * size_y) - adjfile.write('\t\t\t\n' - % (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult)) - adjfile.write('\t\t\n') - adjfile.write('\t\n') - - objFile = open(path, 'w') - objFile.write('v %f %f 0\n' % (-size_x/2, -size_y/2)) - objFile.write('v %f %f 0\n' % ( size_x/2, -size_y/2)) - objFile.write('v %f %f 0\n' % ( size_x/2, size_y/2)) - objFile.write('v %f %f 0\n' % (-size_x/2, size_y/2)) - objFile.write('f 4 3 2 1\n') - objFile.close() - - def _export(self, scene): - import tempfile - self._temp_dir = tempfile.mkdtemp(prefix='mitsuba_'); - self._temp_dae = os.path.join(self._temp_dir, 'scene.dae') - self._temp_xml = os.path.join(self._temp_dir, 'scene.xml') - self._temp_adj = os.path.join(self._temp_dir, 'scene_adjustments.xml') - self._temp_out = os.path.join(self._temp_dir, 'scene.png') - os.mkdir(os.path.join(self._temp_dir, 'meshes')) - print("MtsBlend: Writing COLLADA file") - while True: - try: - bpy.ops.wm.collada_export(filepath=self._temp_dae, check_existing=False) - break - except SystemError: - # Weird SystemError (Operator bpy.ops.wm.collada_export.poll() - # failed, context is incorrect) -> try again - print("MtsBlend: Retrying") - time.sleep(0.1) - print("MtsBlend: Writing adjustments file") - adjfile = open(self._temp_adj, 'w') - adjfile.write('\n'); - idx = 0 - for obj in scene.objects: - if obj.type == 'LAMP': - self._export_lamp(adjfile, obj, idx) - idx = idx+1 - adjfile.write('\n'); - adjfile.close() - - def _render(self): - scene = bpy.data.scenes[0] - (mts_path, tail) = os.path.split(bpy.path.abspath(scene.mts_path)) - mtsimport_binary = os.path.join(mts_path, "mtsimport") - mitsuba_binary = os.path.join(mts_path, "mitsuba") - mts_render_libpath = os.path.join(mts_path, "src/librender") - mts_core_libpath = os.path.join(mts_path, "src/libcore") - mts_hw_libpath = os.path.join(mts_path, "src/libhw") - env = copy.copy(os.environ) - env['LD_LIBRARY_PATH'] = mts_core_libpath + ":" + mts_render_libpath + ":" + mts_hw_libpath - render = scene.render - width = int(render.resolution_x * render.resolution_percentage * 0.01) - height = int(render.resolution_y * render.resolution_percentage * 0.01) - - try: - print("MtsBlend: Launching mtsimport") - process = subprocess.Popen( - [mtsimport_binary, '-s', '-r', '%dx%d' % (width, height), - '-l', 'pngfilm', - self._temp_dae, self._temp_xml, - self._temp_adj], - env = env, - cwd = self._temp_dir - ) - if process.wait() != 0: - print("MtsBlend: mtsimport returned with a nonzero status") - return False - - self._process = subprocess.Popen( - [mitsuba_binary, self._temp_xml, '-o', self._temp_out], - env = env, - cwd = self._temp_dir - ) - except OSError: - print("MtsBlend: Could not execute '%s', possibly Mitsuba isn't installed" % mtsimport_binary) - return False - - return True - - def _cleanup(self): - print("Not cleaning up") - #shutil.rmtree(self._temp_dir) - - def render(self, scene): - self._export(scene) - if not self._render(): - self.update_stats("", "MtsBlend: Unable to render (please check the console)") - return - - r = scene.render - x = int(r.resolution_x * r.resolution_percentage * 0.01) - y = int(r.resolution_y * r.resolution_percentage * 0.01) - DELAY = 0.02 - - # Wait for the file to be created - while not os.path.exists(self._temp_out): - if self.test_break(): - try: - self._process.terminate() - except: - pass - break - - if self._process.poll() != None: - self.update_stats("", "MtsBlend: Failed to render (check console)") - break - - time.sleep(DELAY) - - if os.path.exists(self._temp_out): - self.update_stats("", "MtsBlend: Rendering") - prev_size = -1 - - def update_image(): - result = self.begin_result(0, 0, x, y) - layer = result.layers[0] - try: - print("Loading %s" % self._temp_out) - layer.load_from_file(self._temp_out) - except: - pass - self.end_result(result) - - while True: - if self._process.poll() is not None: - update_image() - break - - if self.test_break(): - try: - self._process.terminate() - except: - pass - - break - - new_size = os.path.getsize(self._temp_out) - if new_size != prev_size: - update_image() - prev_size = new_size - - time.sleep(DELAY) - - self._cleanup() diff --git a/data/blender/mitsuba/ui/render_panels.py b/data/blender/mitsuba/ui/render_panels.py index 9ac5c5fa..882a126a 100644 --- a/data/blender/mitsuba/ui/render_panels.py +++ b/data/blender/mitsuba/ui/render_panels.py @@ -62,6 +62,8 @@ class engine(render_described_context, bpy.types.Panel): binary_path = context.scene.mitsuba_engine.binary_path if binary_path != "" and cached_binary_path != binary_path: binary_path = os.path.abspath(efutil.filesystem_path(binary_path)) + if os.path.isfile(binary_path): + (binary_path, tail) = os.path.split(binary_path) actualChange = cached_binary_path != None cached_binary_path = binary_path context.scene.mitsuba_engine.binary_path = binary_path diff --git a/doc/blender.tex b/doc/blender.tex new file mode 100644 index 00000000..0345edf3 --- /dev/null +++ b/doc/blender.tex @@ -0,0 +1,8 @@ +\section{Blender integration} +% List of things to explain +\subsection{Installing on OSX} +On Mac OS, either copy or symlink the plugin directory (\code{data/blender/mitsuba}) into the appropriate place of the +Blender application bundle (e.g. \code{blender.app/Contents/MacOS/}\textbf{}\code{/scripts/addons/mitsuba}). + +When specifying the Mitsuba executable path, note that you must again provide +the path to the binary within the application bundle, e.g. \code{/Applications/Mitsuba.app/Contents/MacOS/mitsuba} diff --git a/include/mitsuba/render/fwd.h b/include/mitsuba/render/fwd.h index 1482e787..a40e5948 100644 --- a/include/mitsuba/render/fwd.h +++ b/include/mitsuba/render/fwd.h @@ -45,7 +45,7 @@ class Instanced; class Integrator; struct Intersection; class IrradianceCache; -template class AbstractKDTree; +template class KDTreeBase; template class GenericKDTree; class KDTree; class LocalWorker; diff --git a/include/mitsuba/render/gkdtree.h b/include/mitsuba/render/gkdtree.h index c6317cfd..372d8220 100644 --- a/include/mitsuba/render/gkdtree.h +++ b/include/mitsuba/render/gkdtree.h @@ -46,8 +46,8 @@ //#define MTS_KD_MAILBOX_MASK (MTS_KD_MAILBOX_SIZE-1) #if defined(MTS_KD_DEBUG) -#define KDAssert(expr) Assert(expr) -#define KDAssertEx(expr, text) AssertEx(expr, text) +#define KDAssert(expr) SAssert(expr) +#define KDAssertEx(expr, text) SAssertEx(expr, text) #else #define KDAssert(expr) #define KDAssertEx(expr, text) @@ -433,7 +433,7 @@ private: * This class defines the byte layout for KD-tree nodes and * provides methods for querying the tree structure. */ -template class AbstractKDTree : public Object { +template class KDTreeBase : public Object { public: /// Index number format (max 2^32 prims) typedef uint32_t index_type; @@ -616,7 +616,7 @@ public: MTS_DECLARE_CLASS() protected: - virtual ~AbstractKDTree() { } + virtual ~KDTreeBase() { } protected: KDNode *m_nodes; AABBType m_aabb, m_tightAABB; @@ -629,6 +629,9 @@ protected: #pragma float_control(precise, on) #endif +#define KDLog(level, fmt, ...) Thread::getThread()->getLogger()->log(level, KDTreeBase::m_theClass, \ + __FILE__, __LINE__, fmt, ## __VA_ARGS__) + /** * \brief SAH KD-tree acceleration data structure for fast ray-object * intersection computations. @@ -680,7 +683,7 @@ protected: * \author Wenzel Jakob */ template - class GenericKDTree : public AbstractKDTree { + class GenericKDTree : public KDTreeBase { protected: // Some forward declarations struct MinMaxBins; @@ -688,9 +691,9 @@ protected: struct EdgeEventOrdering; public: - typedef typename AbstractKDTree::size_type size_type; - typedef typename AbstractKDTree::index_type index_type; - typedef typename AbstractKDTree::KDNode KDNode; + typedef typename KDTreeBase::size_type size_type; + typedef typename KDTreeBase::index_type index_type; + typedef typename KDTreeBase::KDNode KDNode; typedef typename AABBType::value_type value_type; typedef typename AABBType::point_type point_type; typedef typename AABBType::vector_type vector_type; @@ -918,8 +921,6 @@ public: * and fitting the SAH cost model to the collected statistics. */ void findCosts(Float &traversalCost, Float &intersectionCost); - - MTS_DECLARE_CLASS() protected: /** * \brief Build a KD-tree over the supplied geometry @@ -929,23 +930,23 @@ protected: void buildInternal() { /* Some samity checks */ if (this->isBuilt()) - Log(EError, "The kd-tree has already been built!"); + KDLog(EError, "The kd-tree has already been built!"); if (m_traversalCost <= 0) - Log(EError, "The traveral cost must be > 0"); + KDLog(EError, "The traveral cost must be > 0"); if (m_intersectionCost <= 0) - Log(EError, "The intersection cost must be > 0"); + KDLog(EError, "The intersection cost must be > 0"); if (m_emptySpaceBonus <= 0 || m_emptySpaceBonus > 1) - Log(EError, "The empty space bonus must be in [0, 1]"); + KDLog(EError, "The empty space bonus must be in [0, 1]"); if (m_stopPrims < 0) - Log(EError, "The stopping primitive count must be >= 0"); + KDLog(EError, "The stopping primitive count must be >= 0"); if (m_exactPrimThreshold < 0) - Log(EError, "The exact primitive threshold must be >= 0"); + KDLog(EError, "The exact primitive threshold must be >= 0"); if (m_minMaxBins <= 1) - Log(EError, "The number of min-max bins must be > 2"); + KDLog(EError, "The number of min-max bins must be > 2"); size_type primCount = cast()->getPrimitiveCount(); if (primCount == 0) { - Log(EWarn, "kd-tree contains no geometry!"); + KDLog(EWarn, "kd-tree contains no geometry!"); // +1 shift is for alignment purposes (see KDNode::getSibling) this->m_nodes = static_cast(allocAligned(sizeof(KDNode) * 2))+1; this->m_nodes[0].initLeafNode(0, 0); @@ -959,7 +960,7 @@ protected: m_maxDepth = (int) (8 + 1.3f * log2i(primCount)); m_maxDepth = std::min(m_maxDepth, (size_type) MTS_KD_MAXDEPTH); - Log(EDebug, "Creating a preliminary index list (%s)", + KDLog(EDebug, "Creating a preliminary index list (%s)", memString(primCount * sizeof(index_type)).c_str()); OrderedChunkAllocator &leftAlloc = ctx.leftAlloc; @@ -973,29 +974,29 @@ protected: indices[i] = i; } - Log(EDebug, "Computed scene bounds in %i ms", + KDLog(EDebug, "Computed scene bounds in %i ms", timer->getMilliseconds()); - Log(EDebug, ""); + KDLog(EDebug, ""); - Log(EDebug, "kd-tree configuration:"); - Log(EDebug, " Traversal cost : %.2f", m_traversalCost); - Log(EDebug, " Intersection cost : %.2f", m_intersectionCost); - Log(EDebug, " Empty space bonus : %.2f", m_emptySpaceBonus); - Log(EDebug, " Max. tree depth : %i", m_maxDepth); - Log(EDebug, " Scene bounding box (min) : %s", + KDLog(EDebug, "kd-tree configuration:"); + KDLog(EDebug, " Traversal cost : %.2f", m_traversalCost); + KDLog(EDebug, " Intersection cost : %.2f", m_intersectionCost); + KDLog(EDebug, " Empty space bonus : %.2f", m_emptySpaceBonus); + KDLog(EDebug, " Max. tree depth : %i", m_maxDepth); + KDLog(EDebug, " Scene bounding box (min) : %s", aabb.min.toString().c_str()); - Log(EDebug, " Scene bounding box (max) : %s", + KDLog(EDebug, " Scene bounding box (max) : %s", aabb.max.toString().c_str()); - Log(EDebug, " Min-max bins : %i", m_minMaxBins); - Log(EDebug, " Greedy SAH optimization : use for <= %i primitives", + KDLog(EDebug, " Min-max bins : %i", m_minMaxBins); + KDLog(EDebug, " Greedy SAH optimization : use for <= %i primitives", m_exactPrimThreshold); - Log(EDebug, " Perfect splits : %s", m_clip ? "yes" : "no"); - Log(EDebug, " Retract bad splits : %s", + KDLog(EDebug, " Perfect splits : %s", m_clip ? "yes" : "no"); + KDLog(EDebug, " Retract bad splits : %s", m_retract ? "yes" : "no"); - Log(EDebug, " Stopping primitive count : %i", m_stopPrims); - Log(EDebug, " Build tree in parallel : %s", + KDLog(EDebug, " Stopping primitive count : %i", m_stopPrims); + KDLog(EDebug, " Build tree in parallel : %s", m_parallelBuild ? "yes" : "no"); - Log(EDebug, ""); + KDLog(EDebug, ""); size_type procCount = getProcessorCount(); if (procCount == 1) @@ -1010,7 +1011,7 @@ protected: } } - Log(EInfo, "Constructing a SAH kd-tree (%i primitives) ..", primCount); + KDLog(EInfo, "Constructing a SAH kd-tree (%i primitives) ..", primCount); m_indirectionLock = new Mutex(); KDNode *prelimRoot = ctx.nodes.allocate(1); @@ -1030,17 +1031,17 @@ protected: m_builders[i]->join(); } - Log(EInfo, "Finished -- took %i ms.", timer->getMilliseconds()); - Log(EDebug, ""); + KDLog(EInfo, "Finished -- took %i ms.", timer->getMilliseconds()); + KDLog(EDebug, ""); - Log(EDebug, "Temporary memory statistics:"); - Log(EDebug, " Classification storage : %s", + KDLog(EDebug, "Temporary memory statistics:"); + KDLog(EDebug, " Classification storage : %s", memString((ctx.classStorage.size() * (1+procCount))).c_str()); - Log(EDebug, " Indirection entries : " SIZE_T_FMT " (%s)", + KDLog(EDebug, " Indirection entries : " SIZE_T_FMT " (%s)", m_indirections.size(), memString(m_indirections.capacity() * sizeof(KDNode *)).c_str()); - Log(EDebug, " Main thread:"); + KDLog(EDebug, " Main thread:"); ctx.printStats(); size_t totalUsage = m_indirections.capacity() * sizeof(KDNode *) + ctx.size(); @@ -1049,7 +1050,7 @@ protected: ctx.leftAlloc.cleanup(); ctx.rightAlloc.cleanup(); for (size_type i=0; igetContext(); subCtx.printStats(); totalUsage += subCtx.size(); @@ -1057,11 +1058,11 @@ protected: subCtx.rightAlloc.cleanup(); ctx.accumulateStatisticsFrom(subCtx); } - Log(EDebug, " Total: %s", memString(totalUsage).c_str()); + KDLog(EDebug, " Total: %s", memString(totalUsage).c_str()); - Log(EDebug, ""); + KDLog(EDebug, ""); timer->reset(); - Log(EDebug, "Optimizing memory layout .."); + KDLog(EDebug, "Optimizing memory layout .."); std::stack > stack; @@ -1133,7 +1134,7 @@ protected: float split = node->getSplit(); bool result = target->initInnerNode(axis, split, children - target); if (!result) - Log(EError, "Cannot represent relative pointer -- " + KDLog(EError, "Cannot represent relative pointer -- " "too many primitives?"); Float tmp = aabb.min[axis]; @@ -1148,7 +1149,7 @@ protected: KDAssert(nodePtr == ctx.innerNodeCount + ctx.leafNodeCount); KDAssert(indexPtr == m_indexCount); - Log(EDebug, "Finished -- took %i ms.", timer->getMilliseconds()); + KDLog(EDebug, "Finished -- took %i ms.", timer->getMilliseconds()); /* Free some more memory */ ctx.nodes.clear(); @@ -1167,7 +1168,7 @@ protected: m_builders.clear(); } - Log(EDebug, ""); + KDLog(EDebug, ""); Float rootSA = aabb.getSurfaceArea(); expTraversalSteps /= rootSA; @@ -1184,42 +1185,42 @@ protected: + Vector(Epsilon, Epsilon, Epsilon); this->m_bsphere = aabb.getBSphere(); - Log(EDebug, "Structural kd-tree statistics:"); - Log(EDebug, " Parallel work units : " SIZE_T_FMT, + KDLog(EDebug, "Structural kd-tree statistics:"); + KDLog(EDebug, " Parallel work units : " SIZE_T_FMT, m_interface.threadMap.size()); - Log(EDebug, " Node storage cost : %s", + KDLog(EDebug, " Node storage cost : %s", memString(nodePtr * sizeof(KDNode)).c_str()); - Log(EDebug, " Index storage cost : %s", + KDLog(EDebug, " Index storage cost : %s", memString(indexPtr * sizeof(index_type)).c_str()); - Log(EDebug, " Inner nodes : %i", ctx.innerNodeCount); - Log(EDebug, " Leaf nodes : %i", ctx.leafNodeCount); - Log(EDebug, " Nonempty leaf nodes : %i", + KDLog(EDebug, " Inner nodes : %i", ctx.innerNodeCount); + KDLog(EDebug, " Leaf nodes : %i", ctx.leafNodeCount); + KDLog(EDebug, " Nonempty leaf nodes : %i", ctx.nonemptyLeafNodeCount); std::ostringstream oss; oss << " Leaf node histogram : "; for (size_type i=0; i nodeAABB.max[axis])) { /* When primitive clipping is active, this should never happen! */ - Log(EError, "Internal error: edge event is out of bounds"); + KDLog(EError, "Internal error: edge event is out of bounds"); } #endif } @@ -3184,7 +3185,7 @@ template } } - Log(EDebug, "Fitting to " SIZE_T_FMT " samples (" SIZE_T_FMT + KDLog(EDebug, "Fitting to " SIZE_T_FMT " samples (" SIZE_T_FMT " intersections)", idx, nIntersections); /* Solve using normal equations */ @@ -3200,7 +3201,7 @@ template } M.m[3][3] = 1.0f; bool success = M.invert(Minv); - Assert(success); + SAssert(success); Transform(Minv, M)(rhs, x); @@ -3219,17 +3220,17 @@ template avgRdtsc += b[k]; avgRdtsc /= idx; - Log(EDebug, "Least squares fit:"); - Log(EDebug, " Constant overhead = %.2f", x[0]); - Log(EDebug, " Traversal cost = %.2f", x[1]); - Log(EDebug, " Intersection cost = %.2f", x[2]); - Log(EDebug, " Average rdtsc value = %.2f", avgRdtsc); - Log(EDebug, " Avg. residual = %.2f", avgResidual); + KDLog(EDebug, "Least squares fit:"); + KDLog(EDebug, " Constant overhead = %.2f", x[0]); + KDLog(EDebug, " Traversal cost = %.2f", x[1]); + KDLog(EDebug, " Intersection cost = %.2f", x[2]); + KDLog(EDebug, " Average rdtsc value = %.2f", avgRdtsc); + KDLog(EDebug, " Avg. residual = %.2f", avgResidual); x *= 10/x[1]; - Log(EDebug, "Re-scaled:"); - Log(EDebug, " Constant overhead = %.2f", x[0]); - Log(EDebug, " Traversal cost = %.2f", x[1]); - Log(EDebug, " Intersection cost = %.2f", x[2]); + KDLog(EDebug, "Re-scaled:"); + KDLog(EDebug, " Constant overhead = %.2f", x[0]); + KDLog(EDebug, " Traversal cost = %.2f", x[1]); + KDLog(EDebug, " Intersection cost = %.2f", x[2]); delete[] A; delete[] b; @@ -3238,20 +3239,11 @@ template } template - Class *AbstractKDTree::m_theClass - = new Class("AbstractKDTree", true, "Object"); + Class *KDTreeBase::m_theClass + = new Class("KDTreeBase", true, "Object"); template - const Class *AbstractKDTree::getClass() const { - return m_theClass; -} - -template - Class *GenericKDTree::m_theClass - = new Class("GenericKDTree", true, "AbstractKDTree"); - -template - const Class *GenericKDTree::getClass() const { + const Class *KDTreeBase::getClass() const { return m_theClass; } diff --git a/include/mitsuba/render/shape.h b/include/mitsuba/render/shape.h index a90f3275..ccac89bd 100644 --- a/include/mitsuba/render/shape.h +++ b/include/mitsuba/render/shape.h @@ -252,7 +252,7 @@ public: * the interactive walkthrough. The default implementation * simply returns NULL. */ - virtual const AbstractKDTree *getKDTree() const; + virtual const KDTreeBase *getKDTree() const; /** * \brief Create a triangle mesh approximation of this shape diff --git a/src/librender/kdtree.cpp b/src/librender/kdtree.cpp index 55773dba..422da01f 100644 --- a/src/librender/kdtree.cpp +++ b/src/librender/kdtree.cpp @@ -300,5 +300,5 @@ void KDTree::rayIntersectPacketIncoherent(const RayPacket4 &packet, #endif -MTS_IMPLEMENT_CLASS(KDTree, false, GenericKDTree) +MTS_IMPLEMENT_CLASS(KDTree, false, KDTreeBase) MTS_NAMESPACE_END diff --git a/src/librender/shape.cpp b/src/librender/shape.cpp index 2f15abfc..93519570 100644 --- a/src/librender/shape.cpp +++ b/src/librender/shape.cpp @@ -101,7 +101,7 @@ void Shape::addChild(const std::string &name, ConfigurableObject *child) { } } -const AbstractKDTree *Shape::getKDTree() const { +const KDTreeBase *Shape::getKDTree() const { return NULL; } diff --git a/src/qtgui/preview.cpp b/src/qtgui/preview.cpp index 61ed9111..17b67ca4 100644 --- a/src/qtgui/preview.cpp +++ b/src/qtgui/preview.cpp @@ -541,14 +541,14 @@ void PreviewThread::oglRenderVPL(PreviewQueueEntry &target, const VPL &vpl) { } } -void PreviewThread::oglRenderKDTree(const AbstractKDTree *kdtree) { - std::stack::KDNode *, AABB, uint32_t> > stack; +void PreviewThread::oglRenderKDTree(const KDTreeBase *kdtree) { + std::stack::KDNode *, AABB, uint32_t> > stack; stack.push(boost::make_tuple(kdtree->getRoot(), kdtree->getTightAABB(), 0)); Float brightness = 10.0f; while (!stack.empty()) { - const AbstractKDTree::KDNode *node = boost::get<0>(stack.top()); + const KDTreeBase::KDNode *node = boost::get<0>(stack.top()); AABB aabb = boost::get<1>(stack.top()); int level = boost::get<2>(stack.top()); stack.pop(); diff --git a/src/qtgui/preview.h b/src/qtgui/preview.h index 1eeca0f4..e3ba701c 100644 --- a/src/qtgui/preview.h +++ b/src/qtgui/preview.h @@ -75,7 +75,7 @@ protected: /// Render a single VPL using OpenGL void oglRenderVPL(PreviewQueueEntry &target, const VPL &vpl); /// Render a wireframe visualization of a kd-tree - void oglRenderKDTree(const AbstractKDTree *kdtree); + void oglRenderKDTree(const KDTreeBase *kdtree); /// Render a single VPL using real-time coherent ray tracing void rtrtRenderVPL(PreviewQueueEntry &target, const VPL &vpl); private: diff --git a/src/shapes/hair.cpp b/src/shapes/hair.cpp index 989c8043..a190cfa4 100644 --- a/src/shapes/hair.cpp +++ b/src/shapes/hair.cpp @@ -705,7 +705,7 @@ public: return mesh.get(); } - const AbstractKDTree *getKDTree() const { + const KDTreeBase *getKDTree() const { return m_kdtree.get(); }