miscellaneous bugfixes
parent
221e063330
commit
d631da2187
|
@ -148,7 +148,7 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
||||||
adj.exportMaterial(pm)
|
adj.exportMaterial(pm)
|
||||||
adj.exportPreviewMesh(pm)
|
adj.exportPreviewMesh(pm)
|
||||||
adj.writeFooter()
|
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")
|
mitsuba_binary = os.path.join(mts_path, "mitsuba")
|
||||||
env = copy.copy(os.environ)
|
env = copy.copy(os.environ)
|
||||||
mts_render_libpath = os.path.join(mts_path, "src/librender")
|
mts_render_libpath = os.path.join(mts_path, "src/librender")
|
||||||
|
@ -238,7 +238,7 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
||||||
return
|
return
|
||||||
|
|
||||||
if scene.mitsuba_engine.export_mode == 'render':
|
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")
|
mtsgui_binary = os.path.join(mts_path, "mtsgui")
|
||||||
mitsuba_binary = os.path.join(mts_path, "mitsuba")
|
mitsuba_binary = os.path.join(mts_path, "mitsuba")
|
||||||
env = copy.copy(os.environ)
|
env = copy.copy(os.environ)
|
||||||
|
|
|
@ -171,7 +171,7 @@ class EXPORT_OT_mitsuba(bpy.types.Operator):
|
||||||
self.report({'ERROR'}, 'Mitsuba binary path must be specified!')
|
self.report({'ERROR'}, 'Mitsuba binary path must be specified!')
|
||||||
return {'CANCELLED'}
|
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")
|
mtsimport_binary = os.path.join(mts_path, "mtsimport")
|
||||||
env = copy.copy(os.environ)
|
env = copy.copy(os.environ)
|
||||||
mts_render_libpath = os.path.join(mts_path, "src/librender")
|
mts_render_libpath = os.path.join(mts_path, "src/librender")
|
||||||
|
|
|
@ -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<transform name="toWorld">\n')
|
|
||||||
adjfile.write('\t\t\t<matrix value="')
|
|
||||||
for j in range(0,4):
|
|
||||||
for i in range(0,4):
|
|
||||||
adjfile.write("%f " % trafo[i][j])
|
|
||||||
adjfile.write('"/>\n\t\t</transform>\n')
|
|
||||||
|
|
||||||
|
|
||||||
def _export_lamp(self, adjfile, lamp, idx):
|
|
||||||
if lamp.data.type == 'POINT':
|
|
||||||
adjfile.write('\t<luminaire id="%s-light" type="point">\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<rgb name="intensity" value="%f %f %f"/>\n'
|
|
||||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
|
||||||
adjfile.write('\t</luminaire>\n')
|
|
||||||
elif lamp.data.type == 'AREA':
|
|
||||||
adjfile.write('\t<shape type="obj">\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<string name="filename" value="%s"/>\n' % path)
|
|
||||||
self._export_worldtrafo(adjfile, lamp.matrix_world)
|
|
||||||
|
|
||||||
adjfile.write('\n\t\t<luminaire id="%s-light" type="area">\n' % lamp.data.name)
|
|
||||||
mult = lamp.data.energy * lamp.data.distance * lamp.data.distance / (size_x * size_y)
|
|
||||||
adjfile.write('\t\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
|
||||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
|
||||||
adjfile.write('\t\t</luminaire>\n')
|
|
||||||
adjfile.write('\t</shape>\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('<adjustments>\n');
|
|
||||||
idx = 0
|
|
||||||
for obj in scene.objects:
|
|
||||||
if obj.type == 'LAMP':
|
|
||||||
self._export_lamp(adjfile, obj, idx)
|
|
||||||
idx = idx+1
|
|
||||||
adjfile.write('</adjustments>\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()
|
|
|
@ -62,6 +62,8 @@ class engine(render_described_context, bpy.types.Panel):
|
||||||
binary_path = context.scene.mitsuba_engine.binary_path
|
binary_path = context.scene.mitsuba_engine.binary_path
|
||||||
if binary_path != "" and cached_binary_path != binary_path:
|
if binary_path != "" and cached_binary_path != binary_path:
|
||||||
binary_path = os.path.abspath(efutil.filesystem_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
|
actualChange = cached_binary_path != None
|
||||||
cached_binary_path = binary_path
|
cached_binary_path = binary_path
|
||||||
context.scene.mitsuba_engine.binary_path = binary_path
|
context.scene.mitsuba_engine.binary_path = binary_path
|
||||||
|
|
|
@ -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{<BLENDER VERSION>}\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}
|
|
@ -45,7 +45,7 @@ class Instanced;
|
||||||
class Integrator;
|
class Integrator;
|
||||||
struct Intersection;
|
struct Intersection;
|
||||||
class IrradianceCache;
|
class IrradianceCache;
|
||||||
template <typename AABBType> class AbstractKDTree;
|
template <typename AABBType> class KDTreeBase;
|
||||||
template <typename AABBType, typename Derived> class GenericKDTree;
|
template <typename AABBType, typename Derived> class GenericKDTree;
|
||||||
class KDTree;
|
class KDTree;
|
||||||
class LocalWorker;
|
class LocalWorker;
|
||||||
|
|
|
@ -46,8 +46,8 @@
|
||||||
//#define MTS_KD_MAILBOX_MASK (MTS_KD_MAILBOX_SIZE-1)
|
//#define MTS_KD_MAILBOX_MASK (MTS_KD_MAILBOX_SIZE-1)
|
||||||
|
|
||||||
#if defined(MTS_KD_DEBUG)
|
#if defined(MTS_KD_DEBUG)
|
||||||
#define KDAssert(expr) Assert(expr)
|
#define KDAssert(expr) SAssert(expr)
|
||||||
#define KDAssertEx(expr, text) AssertEx(expr, text)
|
#define KDAssertEx(expr, text) SAssertEx(expr, text)
|
||||||
#else
|
#else
|
||||||
#define KDAssert(expr)
|
#define KDAssert(expr)
|
||||||
#define KDAssertEx(expr, text)
|
#define KDAssertEx(expr, text)
|
||||||
|
@ -433,7 +433,7 @@ private:
|
||||||
* This class defines the byte layout for KD-tree nodes and
|
* This class defines the byte layout for KD-tree nodes and
|
||||||
* provides methods for querying the tree structure.
|
* provides methods for querying the tree structure.
|
||||||
*/
|
*/
|
||||||
template <typename AABBType> class AbstractKDTree : public Object {
|
template <typename AABBType> class KDTreeBase : public Object {
|
||||||
public:
|
public:
|
||||||
/// Index number format (max 2^32 prims)
|
/// Index number format (max 2^32 prims)
|
||||||
typedef uint32_t index_type;
|
typedef uint32_t index_type;
|
||||||
|
@ -616,7 +616,7 @@ public:
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
MTS_DECLARE_CLASS()
|
||||||
protected:
|
protected:
|
||||||
virtual ~AbstractKDTree() { }
|
virtual ~KDTreeBase() { }
|
||||||
protected:
|
protected:
|
||||||
KDNode *m_nodes;
|
KDNode *m_nodes;
|
||||||
AABBType m_aabb, m_tightAABB;
|
AABBType m_aabb, m_tightAABB;
|
||||||
|
@ -629,6 +629,9 @@ protected:
|
||||||
#pragma float_control(precise, on)
|
#pragma float_control(precise, on)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define KDLog(level, fmt, ...) Thread::getThread()->getLogger()->log(level, KDTreeBase<AABB>::m_theClass, \
|
||||||
|
__FILE__, __LINE__, fmt, ## __VA_ARGS__)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SAH KD-tree acceleration data structure for fast ray-object
|
* \brief SAH KD-tree acceleration data structure for fast ray-object
|
||||||
* intersection computations.
|
* intersection computations.
|
||||||
|
@ -680,7 +683,7 @@ protected:
|
||||||
* \author Wenzel Jakob
|
* \author Wenzel Jakob
|
||||||
*/
|
*/
|
||||||
template <typename AABBType, typename Derived>
|
template <typename AABBType, typename Derived>
|
||||||
class GenericKDTree : public AbstractKDTree<AABBType> {
|
class GenericKDTree : public KDTreeBase<AABBType> {
|
||||||
protected:
|
protected:
|
||||||
// Some forward declarations
|
// Some forward declarations
|
||||||
struct MinMaxBins;
|
struct MinMaxBins;
|
||||||
|
@ -688,9 +691,9 @@ protected:
|
||||||
struct EdgeEventOrdering;
|
struct EdgeEventOrdering;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename AbstractKDTree<AABBType>::size_type size_type;
|
typedef typename KDTreeBase<AABBType>::size_type size_type;
|
||||||
typedef typename AbstractKDTree<AABBType>::index_type index_type;
|
typedef typename KDTreeBase<AABBType>::index_type index_type;
|
||||||
typedef typename AbstractKDTree<AABBType>::KDNode KDNode;
|
typedef typename KDTreeBase<AABBType>::KDNode KDNode;
|
||||||
typedef typename AABBType::value_type value_type;
|
typedef typename AABBType::value_type value_type;
|
||||||
typedef typename AABBType::point_type point_type;
|
typedef typename AABBType::point_type point_type;
|
||||||
typedef typename AABBType::vector_type vector_type;
|
typedef typename AABBType::vector_type vector_type;
|
||||||
|
@ -918,8 +921,6 @@ public:
|
||||||
* and fitting the SAH cost model to the collected statistics.
|
* and fitting the SAH cost model to the collected statistics.
|
||||||
*/
|
*/
|
||||||
void findCosts(Float &traversalCost, Float &intersectionCost);
|
void findCosts(Float &traversalCost, Float &intersectionCost);
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* \brief Build a KD-tree over the supplied geometry
|
* \brief Build a KD-tree over the supplied geometry
|
||||||
|
@ -929,23 +930,23 @@ protected:
|
||||||
void buildInternal() {
|
void buildInternal() {
|
||||||
/* Some samity checks */
|
/* Some samity checks */
|
||||||
if (this->isBuilt())
|
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)
|
if (m_traversalCost <= 0)
|
||||||
Log(EError, "The traveral cost must be > 0");
|
KDLog(EError, "The traveral cost must be > 0");
|
||||||
if (m_intersectionCost <= 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)
|
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)
|
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)
|
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)
|
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();
|
size_type primCount = cast()->getPrimitiveCount();
|
||||||
if (primCount == 0) {
|
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)
|
// +1 shift is for alignment purposes (see KDNode::getSibling)
|
||||||
this->m_nodes = static_cast<KDNode *>(allocAligned(sizeof(KDNode) * 2))+1;
|
this->m_nodes = static_cast<KDNode *>(allocAligned(sizeof(KDNode) * 2))+1;
|
||||||
this->m_nodes[0].initLeafNode(0, 0);
|
this->m_nodes[0].initLeafNode(0, 0);
|
||||||
|
@ -959,7 +960,7 @@ protected:
|
||||||
m_maxDepth = (int) (8 + 1.3f * log2i(primCount));
|
m_maxDepth = (int) (8 + 1.3f * log2i(primCount));
|
||||||
m_maxDepth = std::min(m_maxDepth, (size_type) MTS_KD_MAXDEPTH);
|
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());
|
memString(primCount * sizeof(index_type)).c_str());
|
||||||
|
|
||||||
OrderedChunkAllocator &leftAlloc = ctx.leftAlloc;
|
OrderedChunkAllocator &leftAlloc = ctx.leftAlloc;
|
||||||
|
@ -973,29 +974,29 @@ protected:
|
||||||
indices[i] = i;
|
indices[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(EDebug, "Computed scene bounds in %i ms",
|
KDLog(EDebug, "Computed scene bounds in %i ms",
|
||||||
timer->getMilliseconds());
|
timer->getMilliseconds());
|
||||||
Log(EDebug, "");
|
KDLog(EDebug, "");
|
||||||
|
|
||||||
Log(EDebug, "kd-tree configuration:");
|
KDLog(EDebug, "kd-tree configuration:");
|
||||||
Log(EDebug, " Traversal cost : %.2f", m_traversalCost);
|
KDLog(EDebug, " Traversal cost : %.2f", m_traversalCost);
|
||||||
Log(EDebug, " Intersection cost : %.2f", m_intersectionCost);
|
KDLog(EDebug, " Intersection cost : %.2f", m_intersectionCost);
|
||||||
Log(EDebug, " Empty space bonus : %.2f", m_emptySpaceBonus);
|
KDLog(EDebug, " Empty space bonus : %.2f", m_emptySpaceBonus);
|
||||||
Log(EDebug, " Max. tree depth : %i", m_maxDepth);
|
KDLog(EDebug, " Max. tree depth : %i", m_maxDepth);
|
||||||
Log(EDebug, " Scene bounding box (min) : %s",
|
KDLog(EDebug, " Scene bounding box (min) : %s",
|
||||||
aabb.min.toString().c_str());
|
aabb.min.toString().c_str());
|
||||||
Log(EDebug, " Scene bounding box (max) : %s",
|
KDLog(EDebug, " Scene bounding box (max) : %s",
|
||||||
aabb.max.toString().c_str());
|
aabb.max.toString().c_str());
|
||||||
Log(EDebug, " Min-max bins : %i", m_minMaxBins);
|
KDLog(EDebug, " Min-max bins : %i", m_minMaxBins);
|
||||||
Log(EDebug, " Greedy SAH optimization : use for <= %i primitives",
|
KDLog(EDebug, " Greedy SAH optimization : use for <= %i primitives",
|
||||||
m_exactPrimThreshold);
|
m_exactPrimThreshold);
|
||||||
Log(EDebug, " Perfect splits : %s", m_clip ? "yes" : "no");
|
KDLog(EDebug, " Perfect splits : %s", m_clip ? "yes" : "no");
|
||||||
Log(EDebug, " Retract bad splits : %s",
|
KDLog(EDebug, " Retract bad splits : %s",
|
||||||
m_retract ? "yes" : "no");
|
m_retract ? "yes" : "no");
|
||||||
Log(EDebug, " Stopping primitive count : %i", m_stopPrims);
|
KDLog(EDebug, " Stopping primitive count : %i", m_stopPrims);
|
||||||
Log(EDebug, " Build tree in parallel : %s",
|
KDLog(EDebug, " Build tree in parallel : %s",
|
||||||
m_parallelBuild ? "yes" : "no");
|
m_parallelBuild ? "yes" : "no");
|
||||||
Log(EDebug, "");
|
KDLog(EDebug, "");
|
||||||
|
|
||||||
size_type procCount = getProcessorCount();
|
size_type procCount = getProcessorCount();
|
||||||
if (procCount == 1)
|
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();
|
m_indirectionLock = new Mutex();
|
||||||
KDNode *prelimRoot = ctx.nodes.allocate(1);
|
KDNode *prelimRoot = ctx.nodes.allocate(1);
|
||||||
|
@ -1030,17 +1031,17 @@ protected:
|
||||||
m_builders[i]->join();
|
m_builders[i]->join();
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(EInfo, "Finished -- took %i ms.", timer->getMilliseconds());
|
KDLog(EInfo, "Finished -- took %i ms.", timer->getMilliseconds());
|
||||||
Log(EDebug, "");
|
KDLog(EDebug, "");
|
||||||
|
|
||||||
Log(EDebug, "Temporary memory statistics:");
|
KDLog(EDebug, "Temporary memory statistics:");
|
||||||
Log(EDebug, " Classification storage : %s",
|
KDLog(EDebug, " Classification storage : %s",
|
||||||
memString((ctx.classStorage.size() * (1+procCount))).c_str());
|
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()
|
m_indirections.size(), memString(m_indirections.capacity()
|
||||||
* sizeof(KDNode *)).c_str());
|
* sizeof(KDNode *)).c_str());
|
||||||
|
|
||||||
Log(EDebug, " Main thread:");
|
KDLog(EDebug, " Main thread:");
|
||||||
ctx.printStats();
|
ctx.printStats();
|
||||||
size_t totalUsage = m_indirections.capacity()
|
size_t totalUsage = m_indirections.capacity()
|
||||||
* sizeof(KDNode *) + ctx.size();
|
* sizeof(KDNode *) + ctx.size();
|
||||||
|
@ -1049,7 +1050,7 @@ protected:
|
||||||
ctx.leftAlloc.cleanup();
|
ctx.leftAlloc.cleanup();
|
||||||
ctx.rightAlloc.cleanup();
|
ctx.rightAlloc.cleanup();
|
||||||
for (size_type i=0; i<m_builders.size(); ++i) {
|
for (size_type i=0; i<m_builders.size(); ++i) {
|
||||||
Log(EDebug, " Worker thread %i:", i+1);
|
KDLog(EDebug, " Worker thread %i:", i+1);
|
||||||
BuildContext &subCtx = m_builders[i]->getContext();
|
BuildContext &subCtx = m_builders[i]->getContext();
|
||||||
subCtx.printStats();
|
subCtx.printStats();
|
||||||
totalUsage += subCtx.size();
|
totalUsage += subCtx.size();
|
||||||
|
@ -1057,11 +1058,11 @@ protected:
|
||||||
subCtx.rightAlloc.cleanup();
|
subCtx.rightAlloc.cleanup();
|
||||||
ctx.accumulateStatisticsFrom(subCtx);
|
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();
|
timer->reset();
|
||||||
Log(EDebug, "Optimizing memory layout ..");
|
KDLog(EDebug, "Optimizing memory layout ..");
|
||||||
|
|
||||||
std::stack<boost::tuple<const KDNode *, KDNode *,
|
std::stack<boost::tuple<const KDNode *, KDNode *,
|
||||||
const BuildContext *, AABBType> > stack;
|
const BuildContext *, AABBType> > stack;
|
||||||
|
@ -1133,7 +1134,7 @@ protected:
|
||||||
float split = node->getSplit();
|
float split = node->getSplit();
|
||||||
bool result = target->initInnerNode(axis, split, children - target);
|
bool result = target->initInnerNode(axis, split, children - target);
|
||||||
if (!result)
|
if (!result)
|
||||||
Log(EError, "Cannot represent relative pointer -- "
|
KDLog(EError, "Cannot represent relative pointer -- "
|
||||||
"too many primitives?");
|
"too many primitives?");
|
||||||
|
|
||||||
Float tmp = aabb.min[axis];
|
Float tmp = aabb.min[axis];
|
||||||
|
@ -1148,7 +1149,7 @@ protected:
|
||||||
KDAssert(nodePtr == ctx.innerNodeCount + ctx.leafNodeCount);
|
KDAssert(nodePtr == ctx.innerNodeCount + ctx.leafNodeCount);
|
||||||
KDAssert(indexPtr == m_indexCount);
|
KDAssert(indexPtr == m_indexCount);
|
||||||
|
|
||||||
Log(EDebug, "Finished -- took %i ms.", timer->getMilliseconds());
|
KDLog(EDebug, "Finished -- took %i ms.", timer->getMilliseconds());
|
||||||
|
|
||||||
/* Free some more memory */
|
/* Free some more memory */
|
||||||
ctx.nodes.clear();
|
ctx.nodes.clear();
|
||||||
|
@ -1167,7 +1168,7 @@ protected:
|
||||||
m_builders.clear();
|
m_builders.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(EDebug, "");
|
KDLog(EDebug, "");
|
||||||
|
|
||||||
Float rootSA = aabb.getSurfaceArea();
|
Float rootSA = aabb.getSurfaceArea();
|
||||||
expTraversalSteps /= rootSA;
|
expTraversalSteps /= rootSA;
|
||||||
|
@ -1184,42 +1185,42 @@ protected:
|
||||||
+ Vector(Epsilon, Epsilon, Epsilon);
|
+ Vector(Epsilon, Epsilon, Epsilon);
|
||||||
this->m_bsphere = aabb.getBSphere();
|
this->m_bsphere = aabb.getBSphere();
|
||||||
|
|
||||||
Log(EDebug, "Structural kd-tree statistics:");
|
KDLog(EDebug, "Structural kd-tree statistics:");
|
||||||
Log(EDebug, " Parallel work units : " SIZE_T_FMT,
|
KDLog(EDebug, " Parallel work units : " SIZE_T_FMT,
|
||||||
m_interface.threadMap.size());
|
m_interface.threadMap.size());
|
||||||
Log(EDebug, " Node storage cost : %s",
|
KDLog(EDebug, " Node storage cost : %s",
|
||||||
memString(nodePtr * sizeof(KDNode)).c_str());
|
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());
|
memString(indexPtr * sizeof(index_type)).c_str());
|
||||||
Log(EDebug, " Inner nodes : %i", ctx.innerNodeCount);
|
KDLog(EDebug, " Inner nodes : %i", ctx.innerNodeCount);
|
||||||
Log(EDebug, " Leaf nodes : %i", ctx.leafNodeCount);
|
KDLog(EDebug, " Leaf nodes : %i", ctx.leafNodeCount);
|
||||||
Log(EDebug, " Nonempty leaf nodes : %i",
|
KDLog(EDebug, " Nonempty leaf nodes : %i",
|
||||||
ctx.nonemptyLeafNodeCount);
|
ctx.nonemptyLeafNodeCount);
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << " Leaf node histogram : ";
|
oss << " Leaf node histogram : ";
|
||||||
for (size_type i=0; i<primBucketCount; i++) {
|
for (size_type i=0; i<primBucketCount; i++) {
|
||||||
oss << i << "(" << primBuckets[i] << ") ";
|
oss << i << "(" << primBuckets[i] << ") ";
|
||||||
if ((i+1)%4==0 && i+1<primBucketCount) {
|
if ((i+1)%4==0 && i+1<primBucketCount) {
|
||||||
Log(EDebug, "%s", oss.str().c_str());
|
KDLog(EDebug, "%s", oss.str().c_str());
|
||||||
oss.str("");
|
oss.str("");
|
||||||
oss << " ";
|
oss << " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log(EDebug, "%s", oss.str().c_str());
|
KDLog(EDebug, "%s", oss.str().c_str());
|
||||||
Log(EDebug, "");
|
KDLog(EDebug, "");
|
||||||
Log(EDebug, "Qualitative kd-tree statistics:");
|
KDLog(EDebug, "Qualitative kd-tree statistics:");
|
||||||
Log(EDebug, " Retracted splits : %i", ctx.retractedSplits);
|
KDLog(EDebug, " Retracted splits : %i", ctx.retractedSplits);
|
||||||
Log(EDebug, " Pruned primitives : %i", ctx.pruned);
|
KDLog(EDebug, " Pruned primitives : %i", ctx.pruned);
|
||||||
Log(EDebug, " Largest leaf node : %i primitives",
|
KDLog(EDebug, " Largest leaf node : %i primitives",
|
||||||
maxPrimsInLeaf);
|
maxPrimsInLeaf);
|
||||||
Log(EDebug, " Avg. prims/nonempty leaf : %.2f",
|
KDLog(EDebug, " Avg. prims/nonempty leaf : %.2f",
|
||||||
ctx.primIndexCount / (Float) ctx.nonemptyLeafNodeCount);
|
ctx.primIndexCount / (Float) ctx.nonemptyLeafNodeCount);
|
||||||
Log(EDebug, " Expected traversals/ray : %.2f", expTraversalSteps);
|
KDLog(EDebug, " Expected traversals/ray : %.2f", expTraversalSteps);
|
||||||
Log(EDebug, " Expected leaf visits/ray : %.2f", expLeavesVisited);
|
KDLog(EDebug, " Expected leaf visits/ray : %.2f", expLeavesVisited);
|
||||||
Log(EDebug, " Expected prim. visits/ray : %.2f",
|
KDLog(EDebug, " Expected prim. visits/ray : %.2f",
|
||||||
expPrimitivesIntersected);
|
expPrimitivesIntersected);
|
||||||
Log(EDebug, " Final SAH cost : %.2f", sahCost);
|
KDLog(EDebug, " Final SAH cost : %.2f", sahCost);
|
||||||
Log(EDebug, "");
|
KDLog(EDebug, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -1365,16 +1366,16 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
void printStats() {
|
void printStats() {
|
||||||
Log(EDebug, " Left events : " SIZE_T_FMT " chunks (%s)",
|
KDLog(EDebug, " Left events : " SIZE_T_FMT " chunks (%s)",
|
||||||
leftAlloc.getChunkCount(),
|
leftAlloc.getChunkCount(),
|
||||||
memString(leftAlloc.size()).c_str());
|
memString(leftAlloc.size()).c_str());
|
||||||
Log(EDebug, " Right events : " SIZE_T_FMT " chunks (%s)",
|
KDLog(EDebug, " Right events : " SIZE_T_FMT " chunks (%s)",
|
||||||
rightAlloc.getChunkCount(),
|
rightAlloc.getChunkCount(),
|
||||||
memString(rightAlloc.size()).c_str());
|
memString(rightAlloc.size()).c_str());
|
||||||
Log(EDebug, " kd-tree nodes : " SIZE_T_FMT " entries, "
|
KDLog(EDebug, " kd-tree nodes : " SIZE_T_FMT " entries, "
|
||||||
SIZE_T_FMT " blocks (%s)", nodes.size(), nodes.blockCount(),
|
SIZE_T_FMT " blocks (%s)", nodes.size(), nodes.blockCount(),
|
||||||
memString(nodes.capacity() * sizeof(KDNode)).c_str());
|
memString(nodes.capacity() * sizeof(KDNode)).c_str());
|
||||||
Log(EDebug, " Indices : " SIZE_T_FMT " entries, "
|
KDLog(EDebug, " Indices : " SIZE_T_FMT " entries, "
|
||||||
SIZE_T_FMT " blocks (%s)", indices.size(),
|
SIZE_T_FMT " blocks (%s)", indices.size(),
|
||||||
indices.blockCount(), memString(indices.capacity()
|
indices.blockCount(), memString(indices.capacity()
|
||||||
* sizeof(index_type)).c_str());
|
* sizeof(index_type)).c_str());
|
||||||
|
@ -2021,7 +2022,7 @@ protected:
|
||||||
if (m_clip && (pos < nodeAABB.min[axis]
|
if (m_clip && (pos < nodeAABB.min[axis]
|
||||||
|| pos > nodeAABB.max[axis])) {
|
|| pos > nodeAABB.max[axis])) {
|
||||||
/* When primitive clipping is active, this should never happen! */
|
/* 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
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -3184,7 +3185,7 @@ template <typename AABBType, typename Derived>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
" intersections)", idx, nIntersections);
|
||||||
|
|
||||||
/* Solve using normal equations */
|
/* Solve using normal equations */
|
||||||
|
@ -3200,7 +3201,7 @@ template <typename AABBType, typename Derived>
|
||||||
}
|
}
|
||||||
M.m[3][3] = 1.0f;
|
M.m[3][3] = 1.0f;
|
||||||
bool success = M.invert(Minv);
|
bool success = M.invert(Minv);
|
||||||
Assert(success);
|
SAssert(success);
|
||||||
|
|
||||||
Transform(Minv, M)(rhs, x);
|
Transform(Minv, M)(rhs, x);
|
||||||
|
|
||||||
|
@ -3219,17 +3220,17 @@ template <typename AABBType, typename Derived>
|
||||||
avgRdtsc += b[k];
|
avgRdtsc += b[k];
|
||||||
avgRdtsc /= idx;
|
avgRdtsc /= idx;
|
||||||
|
|
||||||
Log(EDebug, "Least squares fit:");
|
KDLog(EDebug, "Least squares fit:");
|
||||||
Log(EDebug, " Constant overhead = %.2f", x[0]);
|
KDLog(EDebug, " Constant overhead = %.2f", x[0]);
|
||||||
Log(EDebug, " Traversal cost = %.2f", x[1]);
|
KDLog(EDebug, " Traversal cost = %.2f", x[1]);
|
||||||
Log(EDebug, " Intersection cost = %.2f", x[2]);
|
KDLog(EDebug, " Intersection cost = %.2f", x[2]);
|
||||||
Log(EDebug, " Average rdtsc value = %.2f", avgRdtsc);
|
KDLog(EDebug, " Average rdtsc value = %.2f", avgRdtsc);
|
||||||
Log(EDebug, " Avg. residual = %.2f", avgResidual);
|
KDLog(EDebug, " Avg. residual = %.2f", avgResidual);
|
||||||
x *= 10/x[1];
|
x *= 10/x[1];
|
||||||
Log(EDebug, "Re-scaled:");
|
KDLog(EDebug, "Re-scaled:");
|
||||||
Log(EDebug, " Constant overhead = %.2f", x[0]);
|
KDLog(EDebug, " Constant overhead = %.2f", x[0]);
|
||||||
Log(EDebug, " Traversal cost = %.2f", x[1]);
|
KDLog(EDebug, " Traversal cost = %.2f", x[1]);
|
||||||
Log(EDebug, " Intersection cost = %.2f", x[2]);
|
KDLog(EDebug, " Intersection cost = %.2f", x[2]);
|
||||||
|
|
||||||
delete[] A;
|
delete[] A;
|
||||||
delete[] b;
|
delete[] b;
|
||||||
|
@ -3238,20 +3239,11 @@ template <typename AABBType, typename Derived>
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename AABBType>
|
template <typename AABBType>
|
||||||
Class *AbstractKDTree<AABBType>::m_theClass
|
Class *KDTreeBase<AABBType>::m_theClass
|
||||||
= new Class("AbstractKDTree", true, "Object");
|
= new Class("KDTreeBase", true, "Object");
|
||||||
|
|
||||||
template <typename AABBType>
|
template <typename AABBType>
|
||||||
const Class *AbstractKDTree<AABBType>::getClass() const {
|
const Class *KDTreeBase<AABBType>::getClass() const {
|
||||||
return m_theClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename AABBType, typename Derived>
|
|
||||||
Class *GenericKDTree<AABBType, Derived>::m_theClass
|
|
||||||
= new Class("GenericKDTree", true, "AbstractKDTree");
|
|
||||||
|
|
||||||
template <typename AABBType, typename Derived>
|
|
||||||
const Class *GenericKDTree<AABBType, Derived>::getClass() const {
|
|
||||||
return m_theClass;
|
return m_theClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -252,7 +252,7 @@ public:
|
||||||
* the interactive walkthrough. The default implementation
|
* the interactive walkthrough. The default implementation
|
||||||
* simply returns NULL.
|
* simply returns NULL.
|
||||||
*/
|
*/
|
||||||
virtual const AbstractKDTree<AABB> *getKDTree() const;
|
virtual const KDTreeBase<AABB> *getKDTree() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Create a triangle mesh approximation of this shape
|
* \brief Create a triangle mesh approximation of this shape
|
||||||
|
|
|
@ -300,5 +300,5 @@ void KDTree::rayIntersectPacketIncoherent(const RayPacket4 &packet,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MTS_IMPLEMENT_CLASS(KDTree, false, GenericKDTree)
|
MTS_IMPLEMENT_CLASS(KDTree, false, KDTreeBase)
|
||||||
MTS_NAMESPACE_END
|
MTS_NAMESPACE_END
|
||||||
|
|
|
@ -101,7 +101,7 @@ void Shape::addChild(const std::string &name, ConfigurableObject *child) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const AbstractKDTree<AABB> *Shape::getKDTree() const {
|
const KDTreeBase<AABB> *Shape::getKDTree() const {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -541,14 +541,14 @@ void PreviewThread::oglRenderVPL(PreviewQueueEntry &target, const VPL &vpl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreviewThread::oglRenderKDTree(const AbstractKDTree<AABB> *kdtree) {
|
void PreviewThread::oglRenderKDTree(const KDTreeBase<AABB> *kdtree) {
|
||||||
std::stack<boost::tuple<const AbstractKDTree<AABB>::KDNode *, AABB, uint32_t> > stack;
|
std::stack<boost::tuple<const KDTreeBase<AABB>::KDNode *, AABB, uint32_t> > stack;
|
||||||
|
|
||||||
stack.push(boost::make_tuple(kdtree->getRoot(), kdtree->getTightAABB(), 0));
|
stack.push(boost::make_tuple(kdtree->getRoot(), kdtree->getTightAABB(), 0));
|
||||||
Float brightness = 10.0f;
|
Float brightness = 10.0f;
|
||||||
|
|
||||||
while (!stack.empty()) {
|
while (!stack.empty()) {
|
||||||
const AbstractKDTree<AABB>::KDNode *node = boost::get<0>(stack.top());
|
const KDTreeBase<AABB>::KDNode *node = boost::get<0>(stack.top());
|
||||||
AABB aabb = boost::get<1>(stack.top());
|
AABB aabb = boost::get<1>(stack.top());
|
||||||
int level = boost::get<2>(stack.top());
|
int level = boost::get<2>(stack.top());
|
||||||
stack.pop();
|
stack.pop();
|
||||||
|
|
|
@ -75,7 +75,7 @@ protected:
|
||||||
/// Render a single VPL using OpenGL
|
/// Render a single VPL using OpenGL
|
||||||
void oglRenderVPL(PreviewQueueEntry &target, const VPL &vpl);
|
void oglRenderVPL(PreviewQueueEntry &target, const VPL &vpl);
|
||||||
/// Render a wireframe visualization of a kd-tree
|
/// Render a wireframe visualization of a kd-tree
|
||||||
void oglRenderKDTree(const AbstractKDTree<AABB> *kdtree);
|
void oglRenderKDTree(const KDTreeBase<AABB> *kdtree);
|
||||||
/// Render a single VPL using real-time coherent ray tracing
|
/// Render a single VPL using real-time coherent ray tracing
|
||||||
void rtrtRenderVPL(PreviewQueueEntry &target, const VPL &vpl);
|
void rtrtRenderVPL(PreviewQueueEntry &target, const VPL &vpl);
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -705,7 +705,7 @@ public:
|
||||||
return mesh.get();
|
return mesh.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
const AbstractKDTree<AABB> *getKDTree() const {
|
const KDTreeBase<AABB> *getKDTree() const {
|
||||||
return m_kdtree.get();
|
return m_kdtree.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue