svn merge ^/trunk/blender -r46000:46100
authorOve Murberg Henriksen <sorayasilvermoon@hotmail.com>
Sun, 6 May 2012 22:19:13 +0000 (22:19 +0000)
committerOve Murberg Henriksen <sorayasilvermoon@hotmail.com>
Sun, 6 May 2012 22:19:13 +0000 (22:19 +0000)
some conflicts. had to backup my code, accept with "tc" and introduce my own code again.
Hope I didnt leave anything out.

660 files changed:
CMakeLists.txt
build_files/buildbot/master.cfg
build_files/buildbot/master_unpack.py
build_files/buildbot/slave_compile.py
build_files/buildbot/slave_pack.py
build_files/scons/tools/btools.py
extern/libmv/CMakeLists.txt
extern/libmv/ChangeLog
extern/libmv/files.txt
extern/libmv/libmv-capi.cpp
extern/libmv/libmv-capi.h
intern/audaspace/intern/AUD_C-API.cpp
intern/audaspace/intern/AUD_C-API.h
intern/audaspace/intern/AUD_FileWriter.cpp
intern/audaspace/intern/AUD_FileWriter.h
intern/audaspace/intern/AUD_Reference.h
intern/audaspace/intern/AUD_ReferenceHandler.cpp
intern/container/CTR_Map.h
intern/cycles/blender/addon/properties.py
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_session.cpp
intern/cycles/blender/blender_sync.cpp
intern/cycles/blender/blender_sync.h
intern/cycles/bvh/CMakeLists.txt
intern/cycles/bvh/bvh.cpp
intern/cycles/bvh/bvh_build.cpp
intern/cycles/bvh/bvh_build.h
intern/cycles/bvh/bvh_node.cpp
intern/cycles/bvh/bvh_node.h
intern/cycles/bvh/bvh_params.h
intern/cycles/bvh/bvh_sort.cpp
intern/cycles/bvh/bvh_sort.h
intern/cycles/device/device.cpp
intern/cycles/device/device.h
intern/cycles/device/device_cpu.cpp
intern/cycles/device/device_multi.cpp
intern/cycles/kernel/kernel_accumulate.h
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/svm/svm_tex_coord.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/integrator.cpp
intern/cycles/render/integrator.h
intern/cycles/render/mesh.cpp
intern/cycles/render/nodes.cpp
intern/cycles/render/object.cpp
intern/cycles/render/session.cpp
intern/cycles/subd/subd_patch.cpp
intern/cycles/util/CMakeLists.txt
intern/cycles/util/util_boundbox.h
intern/cycles/util/util_math.h
intern/cycles/util/util_thread.h
intern/cycles/util/util_transform.cpp
intern/cycles/util/util_types.h
intern/ghost/GHOST_Rect.h
intern/ghost/intern/GHOST_NDOFManager.cpp
intern/guardedalloc/intern/mallocn.c
intern/mikktspace/mikktspace.c
intern/smoke/extern/smoke_API.h
intern/smoke/intern/FLUID_3D.cpp
intern/smoke/intern/FLUID_3D.h
intern/smoke/intern/OBSTACLE.h
intern/smoke/intern/WTURBULENCE.cpp
intern/smoke/intern/smoke_API.cpp
intern/utfconv/utf_winfunc.c
release/plugins/sequence/blur.c
release/plugins/texture/clouds2.c
release/plugins/texture/tiles.c
release/scripts/modules/addon_utils.py
release/scripts/startup/bl_operators/uvcalc_lightmap.py
release/scripts/startup/bl_ui/properties_paint_common.py
release/scripts/startup/bl_ui/properties_physics_common.py
release/scripts/startup/bl_ui/properties_physics_smoke.py
release/scripts/startup/bl_ui/space_clip.py
release/scripts/startup/bl_ui/space_sequencer.py
release/scripts/startup/bl_ui/space_text.py
release/scripts/startup/bl_ui/space_userpref.py
release/scripts/startup/bl_ui/space_view3d.py
release/scripts/startup/bl_ui/space_view3d_toolbar.py
release/scripts/templates/operator_modal_timer.py
source/blender/avi/AVI_avi.h
source/blender/avi/intern/avi.c
source/blender/avi/intern/avirgb.c
source/blender/avi/intern/codecs.c
source/blender/avi/intern/endian.c
source/blender/avi/intern/options.c
source/blender/blenfont/intern/blf_glyph.c
source/blender/blenfont/intern/blf_lang.c
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_brush.h
source/blender/blenkernel/BKE_cloth.h
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/BKE_deform.h
source/blender/blenkernel/BKE_font.h
source/blender/blenkernel/BKE_lattice.h
source/blender/blenkernel/BKE_library.h
source/blender/blenkernel/BKE_mball.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_movieclip.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_ocean.h
source/blender/blenkernel/BKE_softbody.h
source/blender/blenkernel/BKE_text.h
source/blender/blenkernel/depsgraph_private.h
source/blender/blenkernel/intern/CCGSubSurf.c
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/bmfont.c
source/blender/blenkernel/intern/boids.c
source/blender/blenkernel/intern/brush.c
source/blender/blenkernel/intern/bvhutils.c
source/blender/blenkernel/intern/camera.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/colortools.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/context.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/deform.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/blenkernel/intern/editderivedmesh.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/fcurve.c
source/blender/blenkernel/intern/fluidsim.c
source/blender/blenkernel/intern/fmodifier.c
source/blender/blenkernel/intern/font.c
source/blender/blenkernel/intern/gpencil.c
source/blender/blenkernel/intern/group.c
source/blender/blenkernel/intern/idcode.c
source/blender/blenkernel/intern/idprop.c
source/blender/blenkernel/intern/image.c
source/blender/blenkernel/intern/image_gen.c
source/blender/blenkernel/intern/implicit.c
source/blender/blenkernel/intern/ipo.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mball.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/modifiers_bmesh.c
source/blender/blenkernel/intern/movieclip.c
source/blender/blenkernel/intern/multires.c
source/blender/blenkernel/intern/navmesh_conversion.c
source/blender/blenkernel/intern/nla.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/ocean.c
source/blender/blenkernel/intern/packedFile.c
source/blender/blenkernel/intern/paint.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenkernel/intern/property.c
source/blender/blenkernel/intern/report.c
source/blender/blenkernel/intern/sca.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/shrinkwrap.c
source/blender/blenkernel/intern/sketch.c
source/blender/blenkernel/intern/smoke.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenkernel/intern/sound.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenkernel/intern/text.c
source/blender/blenkernel/intern/texture.c
source/blender/blenkernel/intern/tracking.c
source/blender/blenkernel/intern/unit.c
source/blender/blenkernel/intern/writeffmpeg.c
source/blender/blenkernel/intern/writeframeserver.c
source/blender/blenlib/BLI_array.h
source/blender/blenlib/BLI_editVert.h [deleted file]
source/blender/blenlib/BLI_fileops_types.h
source/blender/blenlib/BLI_ghash.h
source/blender/blenlib/BLI_math_geom.h
source/blender/blenlib/BLI_math_vector.h
source/blender/blenlib/BLI_path_util.h
source/blender/blenlib/BLI_utildefines.h
source/blender/blenlib/CMakeLists.txt
source/blender/blenlib/intern/BLI_kdopbvh.c
source/blender/blenlib/intern/BLI_kdtree.c
source/blender/blenlib/intern/DLRB_tree.c
source/blender/blenlib/intern/bpath.c
source/blender/blenlib/intern/dynlib.c
source/blender/blenlib/intern/fileops.c
source/blender/blenlib/intern/freetypefont.c
source/blender/blenlib/intern/graph.c
source/blender/blenlib/intern/jitter.c
source/blender/blenlib/intern/listbase.c
source/blender/blenlib/intern/math_matrix.c
source/blender/blenlib/intern/math_rotation.c
source/blender/blenlib/intern/math_vector.c
source/blender/blenlib/intern/noise.c
source/blender/blenlib/intern/path_util.c
source/blender/blenlib/intern/pbvh.c
source/blender/blenlib/intern/storage.c
source/blender/blenlib/intern/string.c
source/blender/blenlib/intern/string_utf8.c
source/blender/blenlib/intern/threads.c
source/blender/blenlib/intern/winstuff.c
source/blender/blenloader/intern/readblenentry.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/blenpluginapi/iff.h
source/blender/blenpluginapi/intern/pluginapi.c
source/blender/bmesh/CMakeLists.txt
source/blender/bmesh/intern/bmesh_construct.c
source/blender/bmesh/intern/bmesh_core.c
source/blender/bmesh/intern/bmesh_error.h
source/blender/bmesh/intern/bmesh_iterators.c
source/blender/bmesh/intern/bmesh_iterators.h
source/blender/bmesh/intern/bmesh_mesh_conv.c
source/blender/bmesh/intern/bmesh_mods.c
source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/intern/bmesh_operators_private.h
source/blender/bmesh/intern/bmesh_queries.c
source/blender/bmesh/intern/bmesh_queries.h
source/blender/bmesh/intern/bmesh_walkers.c
source/blender/bmesh/intern/bmesh_walkers_impl.c
source/blender/bmesh/operators/bmo_bevel.c
source/blender/bmesh/operators/bmo_connect.c
source/blender/bmesh/operators/bmo_create.c
source/blender/bmesh/operators/bmo_dupe.c
source/blender/bmesh/operators/bmo_extrude.c
source/blender/bmesh/operators/bmo_inset.c
source/blender/bmesh/operators/bmo_join_triangles.c
source/blender/bmesh/operators/bmo_mirror.c
source/blender/bmesh/operators/bmo_removedoubles.c
source/blender/bmesh/operators/bmo_subdivide.c
source/blender/bmesh/operators/bmo_triangulate.c
source/blender/bmesh/operators/bmo_utils.c
source/blender/collada/AnimationExporter.cpp
source/blender/collada/AnimationExporter.h
source/blender/collada/AnimationImporter.cpp
source/blender/collada/AnimationImporter.h
source/blender/collada/ArmatureExporter.cpp
source/blender/collada/ArmatureImporter.cpp
source/blender/collada/ArmatureImporter.h
source/blender/collada/CameraExporter.cpp
source/blender/collada/DocumentExporter.cpp
source/blender/collada/DocumentImporter.cpp
source/blender/collada/EffectExporter.cpp
source/blender/collada/ErrorHandler.cpp
source/blender/collada/ErrorHandler.h
source/blender/collada/ExtraHandler.h
source/blender/collada/ExtraTags.h
source/blender/collada/GeometryExporter.cpp
source/blender/collada/GeometryExporter.h
source/blender/collada/ImageExporter.cpp
source/blender/collada/LightExporter.cpp
source/blender/collada/MaterialExporter.cpp
source/blender/collada/MaterialExporter.h
source/blender/collada/MeshImporter.cpp
source/blender/collada/SceneExporter.cpp
source/blender/collada/TransformReader.cpp
source/blender/collada/TransformWriter.cpp
source/blender/collada/collada_internal.cpp
source/blender/editors/animation/anim_channels_defines.c
source/blender/editors/animation/anim_channels_edit.c
source/blender/editors/animation/anim_deps.c
source/blender/editors/animation/anim_draw.c
source/blender/editors/animation/anim_filter.c
source/blender/editors/animation/anim_ipo_utils.c
source/blender/editors/animation/anim_markers.c
source/blender/editors/animation/drivers.c
source/blender/editors/animation/fmodifier_ui.c
source/blender/editors/animation/keyframes_draw.c
source/blender/editors/animation/keyframes_general.c
source/blender/editors/animation/keyframing.c
source/blender/editors/animation/keyingsets.c
source/blender/editors/armature/armature_intern.h
source/blender/editors/armature/armature_ops.c
source/blender/editors/armature/editarmature.c
source/blender/editors/armature/editarmature_generate.c
source/blender/editors/armature/editarmature_retarget.c
source/blender/editors/armature/editarmature_sketch.c
source/blender/editors/armature/meshlaplacian.c
source/blender/editors/armature/poseSlide.c
source/blender/editors/armature/poseUtils.c
source/blender/editors/armature/poselib.c
source/blender/editors/armature/poseobject.c
source/blender/editors/armature/reeb.c
source/blender/editors/curve/editcurve.c
source/blender/editors/curve/editfont.c
source/blender/editors/gpencil/drawgpencil.c
source/blender/editors/gpencil/editaction_gpencil.c
source/blender/editors/gpencil/gpencil_edit.c
source/blender/editors/gpencil/gpencil_ops.c
source/blender/editors/gpencil/gpencil_paint.c
source/blender/editors/include/ED_anim_api.h
source/blender/editors/include/ED_clip.h
source/blender/editors/include/ED_curve.h
source/blender/editors/include/ED_mesh.h
source/blender/editors/include/ED_screen.h
source/blender/editors/include/ED_uvedit.h
source/blender/editors/include/ED_view3d.h
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/interface_utils.c
source/blender/editors/interface/interface_widgets.c
source/blender/editors/interface/resources.c
source/blender/editors/mesh/editface.c
source/blender/editors/mesh/editmesh_bvh.c
source/blender/editors/mesh/editmesh_bvh.h
source/blender/editors/mesh/editmesh_knife.c
source/blender/editors/mesh/editmesh_loopcut.c
source/blender/editors/mesh/editmesh_rip.c
source/blender/editors/mesh/editmesh_select.c
source/blender/editors/mesh/editmesh_slide.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/editmesh_utils.c
source/blender/editors/mesh/mesh_intern.h
source/blender/editors/mesh/mesh_navmesh.c
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/mesh/meshtools.c
source/blender/editors/metaball/mball_edit.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_bake.c
source/blender/editors/object/object_constraint.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_group.c
source/blender/editors/object/object_hook.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_lattice.c
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_relations.c
source/blender/editors/object/object_select.c
source/blender/editors/object/object_shapekey.c
source/blender/editors/object/object_transform.c
source/blender/editors/object/object_vgroup.c
source/blender/editors/physics/dynamicpaint_ops.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/physics/particle_object.c
source/blender/editors/physics/physics_fluid.c
source/blender/editors/render/render_opengl.c
source/blender/editors/render/render_shading.c
source/blender/editors/screen/area.c
source/blender/editors/screen/glutil.c
source/blender/editors/screen/screen_edit.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/sculpt_paint/paint_cursor.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_ops.c
source/blender/editors/sculpt_paint/paint_stroke.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/sculpt_paint/sculpt_undo.c
source/blender/editors/sound/sound_ops.c
source/blender/editors/space_action/action_edit.c
source/blender/editors/space_action/action_select.c
source/blender/editors/space_action/space_action.c
source/blender/editors/space_buttons/buttons_context.c
source/blender/editors/space_buttons/buttons_header.c
source/blender/editors/space_buttons/space_buttons.c
source/blender/editors/space_clip/clip_buttons.c
source/blender/editors/space_clip/clip_draw.c
source/blender/editors/space_clip/clip_editor.c
source/blender/editors/space_clip/clip_graph_draw.c
source/blender/editors/space_clip/clip_graph_ops.c
source/blender/editors/space_clip/clip_intern.h
source/blender/editors/space_clip/clip_ops.c
source/blender/editors/space_clip/clip_toolbar.c
source/blender/editors/space_clip/clip_utils.c
source/blender/editors/space_clip/space_clip.c
source/blender/editors/space_clip/tracking_ops.c
source/blender/editors/space_file/file_draw.c
source/blender/editors/space_file/file_intern.h
source/blender/editors/space_file/file_ops.c
source/blender/editors/space_file/file_panels.c
source/blender/editors/space_file/filelist.c
source/blender/editors/space_file/filesel.c
source/blender/editors/space_file/fsmenu.c
source/blender/editors/space_file/space_file.c
source/blender/editors/space_graph/graph_buttons.c
source/blender/editors/space_graph/graph_draw.c
source/blender/editors/space_graph/graph_edit.c
source/blender/editors/space_graph/graph_select.c
source/blender/editors/space_graph/graph_utils.c
source/blender/editors/space_graph/space_graph.c
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_image/space_image.c
source/blender/editors/space_info/info_stats.c
source/blender/editors/space_logic/logic_buttons.c
source/blender/editors/space_logic/logic_ops.c
source/blender/editors/space_logic/logic_window.c
source/blender/editors/space_logic/space_logic.c
source/blender/editors/space_nla/nla_buttons.c
source/blender/editors/space_nla/nla_channels.c
source/blender/editors/space_nla/nla_draw.c
source/blender/editors/space_nla/nla_edit.c
source/blender/editors/space_nla/nla_ops.c
source/blender/editors/space_nla/nla_select.c
source/blender/editors/space_nla/space_nla.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_draw.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/node_select.c
source/blender/editors/space_node/node_templates.c
source/blender/editors/space_node/space_node.c
source/blender/editors/space_outliner/outliner_draw.c
source/blender/editors/space_outliner/outliner_edit.c
source/blender/editors/space_outliner/outliner_select.c
source/blender/editors/space_outliner/outliner_tools.c
source/blender/editors/space_outliner/outliner_tree.c
source/blender/editors/space_outliner/space_outliner.c
source/blender/editors/space_sequencer/sequencer_add.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_sequencer/sequencer_intern.h
source/blender/editors/space_sequencer/sequencer_select.c
source/blender/editors/space_sequencer/space_sequencer.c
source/blender/editors/space_text/space_text.c
source/blender/editors/space_text/text_draw.c
source/blender/editors/space_text/text_intern.h
source/blender/editors/space_text/text_ops.c
source/blender/editors/space_text/text_python.c
source/blender/editors/space_time/space_time.c
source/blender/editors/space_userpref/space_userpref.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/drawvolume.c
source/blender/editors/space_view3d/view3d_buttons.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_header.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/space_view3d/view3d_snap.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_constraints.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_input.c
source/blender/editors/transform/transform_manipulator.c
source/blender/editors/transform/transform_ops.c
source/blender/editors/transform/transform_orientations.c
source/blender/editors/transform/transform_snap.c
source/blender/editors/util/crazyspace.c
source/blender/editors/util/numinput.c
source/blender/editors/util/undo.c
source/blender/editors/uvedit/uvedit_draw.c
source/blender/editors/uvedit/uvedit_intern.h
source/blender/editors/uvedit/uvedit_ops.c
source/blender/editors/uvedit/uvedit_smart_stitch.c
source/blender/gpu/intern/gpu_buffers.c
source/blender/gpu/intern/gpu_codegen.c
source/blender/gpu/intern/gpu_draw.c
source/blender/gpu/intern/gpu_extensions.c
source/blender/gpu/intern/gpu_material.c
source/blender/gpu/intern/gpu_shader_material.glsl
source/blender/gpu/intern/gpu_shader_material.glsl.c
source/blender/ikplugin/intern/iksolver_plugin.c
source/blender/ikplugin/intern/itasc_plugin.cpp
source/blender/imbuf/intern/anim_movie.c
source/blender/imbuf/intern/bmp.c
source/blender/imbuf/intern/dds/ColorBlock.cpp
source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
source/blender/imbuf/intern/dds/PixelFormat.h
source/blender/imbuf/intern/filter.c
source/blender/imbuf/intern/imageprocess.c
source/blender/imbuf/intern/indexer.c
source/blender/imbuf/intern/indexer_dv.c
source/blender/imbuf/intern/iris.c
source/blender/imbuf/intern/jp2.c
source/blender/imbuf/intern/jpeg.c
source/blender/imbuf/intern/openexr/openexr_api.cpp
source/blender/imbuf/intern/png.c
source/blender/imbuf/intern/radiance_hdr.c
source/blender/imbuf/intern/readimage.c
source/blender/imbuf/intern/rectop.c
source/blender/imbuf/intern/scaling.c
source/blender/imbuf/intern/targa.c
source/blender/imbuf/intern/thumbs.c
source/blender/imbuf/intern/util.c
source/blender/makesdna/DNA_brush_types.h
source/blender/makesdna/DNA_listBase.h
source/blender/makesdna/DNA_meshdata_types.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesdna/DNA_object_fluidsim.h
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_smoke_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_tracking_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/intern/dna_genfile.c
source/blender/makesdna/intern/makesdna.c
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_action.c
source/blender/makesrna/intern/rna_actuator.c
source/blender/makesrna/intern/rna_boid.c
source/blender/makesrna/intern/rna_brush.c
source/blender/makesrna/intern/rna_constraint.c
source/blender/makesrna/intern/rna_curve.c
source/blender/makesrna/intern/rna_fcurve.c
source/blender/makesrna/intern/rna_fluidsim.c
source/blender/makesrna/intern/rna_image.c
source/blender/makesrna/intern/rna_lamp.c
source/blender/makesrna/intern/rna_main.c
source/blender/makesrna/intern/rna_main_api.c
source/blender/makesrna/intern/rna_material.c
source/blender/makesrna/intern/rna_meta.c
source/blender/makesrna/intern/rna_modifier.c
source/blender/makesrna/intern/rna_movieclip.c
source/blender/makesrna/intern/rna_nodetree.c
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_object_api.c
source/blender/makesrna/intern/rna_object_force.c
source/blender/makesrna/intern/rna_particle.c
source/blender/makesrna/intern/rna_pose.c
source/blender/makesrna/intern/rna_property.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sensor.c
source/blender/makesrna/intern/rna_sequencer.c
source/blender/makesrna/intern/rna_smoke.c
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_texture.c
source/blender/makesrna/intern/rna_texture_api.c
source/blender/makesrna/intern/rna_tracking.c
source/blender/makesrna/intern/rna_ui.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/makesrna/intern/rna_wm.c
source/blender/modifiers/intern/MOD_boolean.c
source/blender/modifiers/intern/MOD_boolean_util.c
source/blender/modifiers/intern/MOD_cast.c
source/blender/modifiers/intern/MOD_collision.c
source/blender/modifiers/intern/MOD_displace.c
source/blender/modifiers/intern/MOD_explode.c
source/blender/modifiers/intern/MOD_fluidsim_util.c
source/blender/modifiers/intern/MOD_hook.c
source/blender/modifiers/intern/MOD_mask.c
source/blender/modifiers/intern/MOD_particleinstance.c
source/blender/modifiers/intern/MOD_remesh.c
source/blender/modifiers/intern/MOD_screw.c
source/blender/modifiers/intern/MOD_simpledeform.c
source/blender/modifiers/intern/MOD_util.c
source/blender/modifiers/intern/MOD_uvproject.c
source/blender/modifiers/intern/MOD_warp.c
source/blender/modifiers/intern/MOD_wave.c
source/blender/modifiers/intern/MOD_weightvg_util.c
source/blender/nodes/composite/node_composite_util.c
source/blender/nodes/composite/nodes/node_composite_bilateralblur.c
source/blender/nodes/composite/nodes/node_composite_channelMatte.c
source/blender/nodes/composite/nodes/node_composite_chromaMatte.c
source/blender/nodes/composite/nodes/node_composite_colorMatte.c
source/blender/nodes/composite/nodes/node_composite_colorSpill.c
source/blender/nodes/composite/nodes/node_composite_colorbalance.c
source/blender/nodes/composite/nodes/node_composite_diffMatte.c
source/blender/nodes/composite/nodes/node_composite_directionalblur.c
source/blender/nodes/composite/nodes/node_composite_distanceMatte.c
source/blender/nodes/composite/nodes/node_composite_doubleEdgeMask.c
source/blender/nodes/composite/nodes/node_composite_filter.c
source/blender/nodes/composite/nodes/node_composite_gamma.c
source/blender/nodes/composite/nodes/node_composite_glare.c
source/blender/nodes/composite/nodes/node_composite_hueSatVal.c
source/blender/nodes/composite/nodes/node_composite_image.c
source/blender/nodes/composite/nodes/node_composite_levels.c
source/blender/nodes/composite/nodes/node_composite_lummaMatte.c
source/blender/nodes/composite/nodes/node_composite_math.c
source/blender/nodes/composite/nodes/node_composite_movieclip.c
source/blender/nodes/composite/nodes/node_composite_moviedistortion.c
source/blender/nodes/composite/nodes/node_composite_rotate.c
source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c
source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c
source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c
source/blender/nodes/composite/nodes/node_composite_stabilize2d.c
source/blender/nodes/composite/nodes/node_composite_texture.c
source/blender/nodes/composite/nodes/node_composite_tonemap.c
source/blender/nodes/composite/nodes/node_composite_transform.c
source/blender/nodes/intern/node_common.c
source/blender/nodes/intern/node_socket.c
source/blender/nodes/shader/node_shader_util.c
source/blender/nodes/shader/nodes/node_shader_math.c
source/blender/nodes/shader/nodes/node_shader_tex_coord.c
source/blender/nodes/shader/nodes/node_shader_texture.c
source/blender/nodes/shader/nodes/node_shader_vectMath.c
source/blender/nodes/texture/nodes/node_texture_bricks.c
source/blender/nodes/texture/nodes/node_texture_image.c
source/blender/nodes/texture/nodes/node_texture_math.c
source/blender/nodes/texture/nodes/node_texture_mixRgb.c
source/blender/nodes/texture/nodes/node_texture_output.c
source/blender/nodes/texture/nodes/node_texture_texture.c
source/blender/python/bmesh/bmesh_py_types_meshdata.c
source/blender/python/intern/bpy_rna.c
source/blender/python/mathutils/mathutils_geometry.c
source/blender/quicktime/apple/quicktime_export.c
source/blender/quicktime/apple/quicktime_import.c
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/sunsky.h
source/blender/render/intern/raytrace/bvh.h
source/blender/render/intern/raytrace/rayobject.cpp
source/blender/render/intern/raytrace/rayobject_blibvh.cpp
source/blender/render/intern/raytrace/rayobject_hint.h
source/blender/render/intern/raytrace/rayobject_instance.cpp
source/blender/render/intern/raytrace/rayobject_octree.cpp
source/blender/render/intern/raytrace/rayobject_qbvh.cpp
source/blender/render/intern/raytrace/rayobject_rtbuild.cpp
source/blender/render/intern/raytrace/rayobject_svbvh.cpp
source/blender/render/intern/raytrace/rayobject_vbvh.cpp
source/blender/render/intern/raytrace/reorganize.h
source/blender/render/intern/raytrace/svbvh.h
source/blender/render/intern/raytrace/vbvh.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/envmap.c
source/blender/render/intern/source/imagetexture.c
source/blender/render/intern/source/initrender.c
source/blender/render/intern/source/occlusion.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/pixelshading.c
source/blender/render/intern/source/pointdensity.c
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/render_result.c
source/blender/render/intern/source/render_texture.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/renderdatabase.c
source/blender/render/intern/source/shadbuf.c
source/blender/render/intern/source/shadeoutput.c
source/blender/render/intern/source/sss.c
source/blender/render/intern/source/strand.c
source/blender/render/intern/source/sunsky.c
source/blender/render/intern/source/volume_precache.c
source/blender/render/intern/source/volumetric.c
source/blender/render/intern/source/voxeldata.c
source/blender/render/intern/source/zbuf.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_init_exit.c
source/blender/windowmanager/intern/wm_keymap.c
source/blender/windowmanager/intern/wm_operators.c
source/blenderplayer/bad_level_call_stubs/stubs.c
source/gameengine/BlenderRoutines/CMakeLists.txt
source/gameengine/BlenderRoutines/SConscript
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/CMakeLists.txt
source/gameengine/Converter/SConscript
source/gameengine/Ketsji/BL_Shader.h
source/gameengine/Ketsji/CMakeLists.txt
source/gameengine/Ketsji/KX_BlenderMaterial.h
source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
source/gameengine/Ketsji/KX_FontObject.h
source/gameengine/Ketsji/KX_KetsjiEngine.cpp
source/gameengine/Ketsji/KX_PyMath.h
source/gameengine/Ketsji/SConscript
source/gameengine/Rasterizer/RAS_ICanvas.h
source/gameengine/VideoTexture/ImageRender.cpp

index 6a9ca35cd0537909cbc633c01c6710b2a193261f..16de9a4055e72c4e5e8a9effc509a98dbc5c1d6e 100644 (file)
@@ -827,7 +827,7 @@ elseif(WIN32)
                set(CMAKE_C_FLAGS_RELWITHDEBINFO "/O2 /Ob1 /MT /Zi" CACHE STRING "MSVC MT flags " FORCE)
 
                # most msvc warnings are C & C++
-               set(_WARNINGS "/W3 /wd4018 /wd4244 /wd4305 /wd4800 /wd4181 /wd4065 /wd4267 /we4013")
+               set(_WARNINGS "/W3 /wd4018 /wd4244 /wd4305 /wd4800 /wd4181 /wd4065 /wd4267 /we4013 /wd4200")
                set(C_WARNINGS "${_WARNINGS}")
                set(CXX_WARNINGS "${_WARNINGS}")
                unset(_WARNINGS)
index 23751f7dcd49a6a072c58a70fac979580cb2d791..066c133d3357d085ab95926d3e21a59f0ec5f1a6 100644 (file)
@@ -117,6 +117,8 @@ add_builder(c, 'salad_linux_x86_64_scons', '', generic_builder, 'soc-2011-salad'
 add_builder(c, 'win32_scons', 'windows', generic_builder)
 add_builder(c, 'salad_win32_scons', 'windows', generic_builder, 'soc-2011-salad')
 add_builder(c, 'win64_scons', 'win64', generic_builder)
+add_builder(c, 'mingw_win64_scons', 'mingw64', generic_builder)
+add_builder(c, 'mingw_win32_scons', 'mingw32', generic_builder)
 #add_builder(c, 'freebsd_i386_cmake', '', generic_builder)
 #add_builder(c, 'freebsd_x86_64_cmake', '', generic_builder)
 
index 3df22ad8745c2c1836be4059bdb84b4ced298f3d..f67bd294496a0e2da08166b407f753978907614c 100644 (file)
@@ -48,7 +48,8 @@ def get_platform(filename):
     tokens = filename.split("-")
     platforms = ('osx', 'mac', 'bsd',
                  'win', 'linux', 'source',
-                 'solaris')
+                 'solaris',
+                 'mingw')
     platform_tokens = []
     found = False
 
index 209253296be04903d4106b7902ea5803ccedfcaa..eafdf0868cd4a10951864d31742705440de4638d 100644 (file)
@@ -117,6 +117,8 @@ else:
             scons_options.append('BF_BITNESS=' + bitness)
             scons_options.append('WITH_BF_CYCLES_CUDA_BINARIES=True')
             scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc.exe')
+            if builder.find('mingw') != -1:
+                scons_options.append('BF_TOOLSET=mingw')
 
         retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
         sys.exit(retcode)
index cb02e619c1dc03710b895be280ff897d9cd6281e..73c633d0c29cc2fed5c3857b4114521387f464f0 100644 (file)
@@ -81,6 +81,8 @@ if builder.find('scons') != -1:
             scons_options.append('BF_BITNESS=' + bitness)
             scons_options.append('WITH_BF_CYCLES_CUDA_BINARIES=True')
             scons_options.append('BF_CYCLES_CUDA_NVCC=nvcc.exe')
+            if builder.find('mingw') != -1:
+                scons_options.append('BF_TOOLSET=mingw')
 
         retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options)
         sys.exit(retcode)
index efc80fcd3c58c9f4ffb947d4e27538162044cf46..65593d559ed1ff122e4132c9bcb22bca37460dcf 100644 (file)
@@ -622,7 +622,13 @@ def buildslave(target=None, source=None, env=None):
     else:
         extension = '.tar.bz2'
 
-    platform = env['OURPLATFORM'].split('-')[0]
+    if env['OURPLATFORM'] == 'win32-mingw':
+        platform = 'mingw32'
+    elif env['OURPLATFORM'] == 'win64-mingw':
+        platform = 'mingw64'
+    else:
+        platform = env['OURPLATFORM'].split('-')[0]
+
     if platform == 'linux':
         import platform
 
index 02723b64b625430282ba88b8a54429a6ebce0af7..6be813883ec9544908367802f57b6267e07ba6d3 100644 (file)
@@ -69,6 +69,7 @@ set(SRC
        libmv/simple_pipeline/detect.cc
        libmv/simple_pipeline/initialize_reconstruction.cc
        libmv/simple_pipeline/intersect.cc
+       libmv/simple_pipeline/modal_solver.cc
        libmv/simple_pipeline/pipeline.cc
        libmv/simple_pipeline/reconstruction.cc
        libmv/simple_pipeline/resect.cc
@@ -126,6 +127,7 @@ set(SRC
        libmv/simple_pipeline/detect.h
        libmv/simple_pipeline/initialize_reconstruction.h
        libmv/simple_pipeline/intersect.h
+       libmv/simple_pipeline/modal_solver.h
        libmv/simple_pipeline/pipeline.h
        libmv/simple_pipeline/reconstruction.h
        libmv/simple_pipeline/resect.h
index 33068bddf90d627a748e1fbfc23c1555917c8ade..7248e4c9cd98d30f9557658efd906c295d9fa891 100644 (file)
@@ -1,3 +1,16 @@
+commit a44312a7beb2963b8e3bf8015c516d2eff40cc3d
+Author: Sergey Sharybin <sergey.vfx@gmail.com>
+Date:   Thu Apr 12 13:56:02 2012 +0600
+
+    Added solver for modal camera motion, currently supports only tripod solving
+    
+    This solver is intended to deal with such camera motions as tripod and panning,
+    where it's impossible to reconstruct exact position of markers in 3d view.
+    
+    It projects markers onto sphere and uses rigid registration of rotation to
+    find rotation angles which makes bundles from previous and current frame be
+    as closest as it's possible.
+
 commit fa3842e472e3b9c789e47bf6d8f592aa40a84f16
 Author: Sergey Sharybin <sergey.vfx@gmail.com>
 Date:   Thu Apr 12 12:32:48 2012 +0600
@@ -520,9 +533,3 @@ Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
 Date:   Fri Aug 19 16:04:37 2011 +0200
 
     MSVC compatibility: heap allocate pattern, explicit float cast.
-
-commit 702658d2f8616964a6eeb3743fd85e97ac7ff09d
-Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
-Date:   Fri Aug 19 14:59:24 2011 +0200
-
-    Expose regularization parameters (areaPenalty and conditionPenalty) in API.
index 1e564d3a2f27dab75f6a4d3bc8a13a65b9cc3099..85d09ce05b80a3dc93be39d6b076b810be6d6584 100644 (file)
@@ -42,6 +42,8 @@ libmv/simple_pipeline/initialize_reconstruction.cc
 libmv/simple_pipeline/initialize_reconstruction.h
 libmv/simple_pipeline/intersect.cc
 libmv/simple_pipeline/intersect.h
+libmv/simple_pipeline/modal_solver.cc
+libmv/simple_pipeline/modal_solver.h
 libmv/simple_pipeline/pipeline.cc
 libmv/simple_pipeline/pipeline.h
 libmv/simple_pipeline/reconstruction.cc
index e4708e5907d125574a742b7a014f2d5900aec952..6c20d76eeac900626c1d25437e8e874edf880dc5 100644 (file)
@@ -54,6 +54,7 @@
 #include "libmv/simple_pipeline/pipeline.h"
 #include "libmv/simple_pipeline/camera_intrinsics.h"
 #include "libmv/simple_pipeline/rigid_registration.h"
+#include "libmv/simple_pipeline/modal_solver.h"
 
 #include <stdlib.h>
 #include <assert.h>
@@ -384,6 +385,31 @@ int libmv_refineParametersAreValid(int parameters) {
                               LIBMV_REFINE_RADIAL_DISTORTION_K1));
 }
 
+void libmv_solveRefineIntrinsics(libmv::Tracks *tracks, libmv::CameraIntrinsics *intrinsics,
+                       libmv::EuclideanReconstruction *reconstruction, int refine_intrinsics,
+                       reconstruct_progress_update_cb progress_update_callback, void *callback_customdata)
+{
+       /* only a few combinations are supported but trust the caller */
+       int libmv_refine_flags = 0;
+
+       if (refine_intrinsics & LIBMV_REFINE_FOCAL_LENGTH) {
+               libmv_refine_flags |= libmv::BUNDLE_FOCAL_LENGTH;
+       }
+       if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) {
+               libmv_refine_flags |= libmv::BUNDLE_PRINCIPAL_POINT;
+       }
+       if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) {
+               libmv_refine_flags |= libmv::BUNDLE_RADIAL_K1;
+       }
+       if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) {
+               libmv_refine_flags |= libmv::BUNDLE_RADIAL_K2;
+       }
+
+       progress_update_callback(callback_customdata, 1.0, "Refining solution");
+
+       libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags,
+               reconstruction, intrinsics);
+}
 
 libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyframe1, int keyframe2,
                        int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
@@ -423,26 +449,45 @@ libmv_Reconstruction *libmv_solveReconstruction(libmv_Tracks *tracks, int keyfra
        libmv::EuclideanCompleteReconstruction(normalized_tracks, reconstruction, &update_callback);
 
        if (refine_intrinsics) {
-               /* only a few combinations are supported but trust the caller */
-               int libmv_refine_flags = 0;
-               if (refine_intrinsics & LIBMV_REFINE_FOCAL_LENGTH) {
-                       libmv_refine_flags |= libmv::BUNDLE_FOCAL_LENGTH;
-               }
-               if (refine_intrinsics & LIBMV_REFINE_PRINCIPAL_POINT) {
-                       libmv_refine_flags |= libmv::BUNDLE_PRINCIPAL_POINT;
-               }
-               if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K1) {
-                       libmv_refine_flags |= libmv::BUNDLE_RADIAL_K1;
-               }
-               if (refine_intrinsics & LIBMV_REFINE_RADIAL_DISTORTION_K2) {
-                       libmv_refine_flags |= libmv::BUNDLE_RADIAL_K2;
-               }
+               libmv_solveRefineIntrinsics((libmv::Tracks *)tracks, intrinsics, reconstruction,
+                       refine_intrinsics, progress_update_callback, callback_customdata);
+       }
 
-               progress_update_callback(callback_customdata, 1.0, "Refining solution");
-               libmv::EuclideanBundleCommonIntrinsics(*(libmv::Tracks *)tracks, libmv_refine_flags,
-                       reconstruction, intrinsics);
+       progress_update_callback(callback_customdata, 1.0, "Finishing solution");
+       libmv_reconstruction->tracks = *(libmv::Tracks *)tracks;
+       libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics);
+
+       return (libmv_Reconstruction *)libmv_reconstruction;
+}
+
+struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, double focal_length,
+                       double principal_x, double principal_y, double k1, double k2, double k3,
+                       reconstruct_progress_update_cb progress_update_callback, void *callback_customdata)
+{
+       /* Invert the camera intrinsics. */
+       libmv::vector<libmv::Marker> markers = ((libmv::Tracks*)tracks)->AllMarkers();
+       libmv_Reconstruction *libmv_reconstruction = new libmv_Reconstruction();
+       libmv::EuclideanReconstruction *reconstruction = &libmv_reconstruction->reconstruction;
+       libmv::CameraIntrinsics *intrinsics = &libmv_reconstruction->intrinsics;
+
+       ReconstructUpdateCallback update_callback =
+               ReconstructUpdateCallback(progress_update_callback, callback_customdata);
+
+       intrinsics->SetFocalLength(focal_length, focal_length);
+       intrinsics->SetPrincipalPoint(principal_x, principal_y);
+       intrinsics->SetRadialDistortion(k1, k2, k3);
+
+       for (int i = 0; i < markers.size(); ++i) {
+               intrinsics->InvertIntrinsics(markers[i].x,
+                       markers[i].y,
+                       &(markers[i].x),
+                       &(markers[i].y));
        }
 
+       libmv::Tracks normalized_tracks(markers);
+
+       libmv::ModalSolver(normalized_tracks, reconstruction, &update_callback);
+
        progress_update_callback(callback_customdata, 1.0, "Finishing solution");
        libmv_reconstruction->tracks = *(libmv::Tracks *)tracks;
        libmv_reconstruction->error = libmv::EuclideanReprojectionError(*(libmv::Tracks *)tracks, *reconstruction, *intrinsics);
index 010198323741176c192f6960b083a8b53495127c..bccc47068322741badca2c1d68a1c60f1827217f 100644 (file)
@@ -68,6 +68,9 @@ int libmv_refineParametersAreValid(int parameters);
 struct libmv_Reconstruction *libmv_solveReconstruction(struct libmv_Tracks *tracks, int keyframe1, int keyframe2,
                        int refine_intrinsics, double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
                        reconstruct_progress_update_cb progress_update_callback, void *callback_customdata);
+struct libmv_Reconstruction *libmv_solveModal(struct libmv_Tracks *tracks, double focal_length,
+                       double principal_x, double principal_y, double k1, double k2, double k3,
+                       reconstruct_progress_update_cb progress_update_callback, void *callback_customdata);
 int libmv_reporojectionPointForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track, double pos[3]);
 double libmv_reporojectionErrorForTrack(struct libmv_Reconstruction *libmv_reconstruction, int track);
 double libmv_reporojectionErrorForImage(struct libmv_Reconstruction *libmv_reconstruction, int image);
index 9100a277124b67a5e0a7f59acf366b277fe7828f..50b476506969a014356a386eec367f19fce66b9f 100644 (file)
@@ -41,6 +41,7 @@
 #include <cstdlib>
 #include <cstring>
 #include <cmath>
+#include <sstream>
 
 #include "AUD_NULLDevice.h"
 #include "AUD_I3DDevice.h"
@@ -1236,6 +1237,47 @@ const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int lengt
        }
 }
 
+const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate)
+{
+       try
+       {
+               AUD_SequencerFactory* f = dynamic_cast<AUD_SequencerFactory*>(sound->get());
+
+               f->setSpecs(specs.specs);
+
+               std::vector<AUD_Reference<AUD_IWriter> > writers;
+
+               int channels = specs.channels;
+               specs.channels = AUD_CHANNELS_MONO;
+
+               for(int i = 0; i < channels; i++)
+               {
+                       std::stringstream stream;
+                       std::string fn = filename;
+                       size_t index = fn.find_last_of('.');
+                       size_t index_slash = fn.find_last_of('/');
+                       size_t index_backslash = fn.find_last_of('\\');
+                       if((index == std::string::npos) ||
+                                       ((index < index_slash) && (index_slash != std::string::npos)) ||
+                                       ((index < index_backslash) && (index_backslash != std::string::npos)))
+                               stream << filename << "_" << (i + 1);
+                       else
+                               stream << fn.substr(0, index) << "_" << (i + 1) << fn.substr(index);
+                       writers.push_back(AUD_FileWriter::createWriter(stream.str(), specs, format, codec, bitrate));
+               }
+
+               AUD_Reference<AUD_IReader> reader = f->createQualityReader();
+               reader->seek(start);
+               AUD_FileWriter::writeReader(reader, writers, length, buffersize);
+
+               return NULL;
+       }
+       catch(AUD_Exception& e)
+       {
+               return e.str;
+       }
+}
+
 AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start)
 {
        try
index 8388af2170d45b5dc4b9d7116e21d6f53bacb207..a52a1fa836954cfc5f0434b2d0de8ad15ac021a4 100644 (file)
@@ -709,6 +709,21 @@ extern void* AUD_getSet(void* set);
  */
 extern const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
 
+/**
+ * Mixes a sound down into multiple files.
+ * \param sound The sound scene to mix down.
+ * \param start The start frame.
+ * \param length The count of frames to write.
+ * \param buffersize How many samples should be written at once.
+ * \param filename The file to write to, the channel number and an underscore are added at the beginning.
+ * \param specs The file's audio specification.
+ * \param format The file's container format.
+ * \param codec The codec used for encoding the audio data.
+ * \param bitrate The bitrate for encoding.
+ * \return An error message or NULL in case of success.
+ */
+extern const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
+
 /**
  * Opens a read device and prepares it for mixdown of the sound scene.
  * \param specs Output audio specifications.
index df76b667e3fe843abd703a6d50f1c5c09be91e33..f74021acad19a45d328c6f75f7071bcf1d449b92 100644 (file)
@@ -93,3 +93,39 @@ void AUD_FileWriter::writeReader(AUD_Reference<AUD_IReader> reader, AUD_Referenc
                writer->write(len, buf);
        }
 }
+
+void AUD_FileWriter::writeReader(AUD_Reference<AUD_IReader> reader, std::vector<AUD_Reference<AUD_IWriter> >& writers, unsigned int length, unsigned int buffersize)
+{
+       AUD_Buffer buffer(buffersize * AUD_SAMPLE_SIZE(reader->getSpecs()));
+       AUD_Buffer buffer2(buffersize * sizeof(sample_t));
+       sample_t* buf = buffer.getBuffer();
+       sample_t* buf2 = buffer2.getBuffer();
+
+       int len;
+       bool eos = false;
+       int channels = reader->getSpecs().channels;
+
+       for(unsigned int pos = 0; ((pos < length) || (length <= 0)) && !eos; pos += len)
+       {
+               len = buffersize;
+               if((len > length - pos) && (length > 0))
+                       len = length - pos;
+               reader->read(len, eos, buf);
+
+               for(int channel = 0; channel < channels; channel++)
+               {
+                       for(int i = 0; i < len; i++)
+                       {
+                               // clamping!
+                               if(buf[i * channels + channel] > 1)
+                                       buf2[i] = 1;
+                               else if(buf[i * channels + channel] < -1)
+                                       buf2[i] = -1;
+                               else
+                                       buf2[i] = buf[i * channels + channel];
+                       }
+
+                       writers[channel]->write(len, buf2);
+               }
+       }
+}
index c9ee2b1ee12046baae22523256f56be9b852b6e7..385aba5ef45867c15c405f3f79be129e2df41d72 100644 (file)
@@ -31,6 +31,7 @@
 #define __AUD_FILEWRITER_H__
 
 #include <string>
+#include <vector>
 
 #include "AUD_Reference.h"
 
@@ -68,6 +69,15 @@ public:
         * \param buffersize How many samples should be transfered at once.
         */
        static void writeReader(AUD_Reference<AUD_IReader> reader, AUD_Reference<AUD_IWriter> writer, unsigned int length, unsigned int buffersize);
+
+       /**
+        * Writes a reader to several writers.
+        * \param reader The reader to read from.
+        * \param writers The writers to write to.
+        * \param length How many samples should be transfered.
+        * \param buffersize How many samples should be transfered at once.
+        */
+       static void writeReader(AUD_Reference<AUD_IReader> reader, std::vector<AUD_Reference<AUD_IWriter> >& writers, unsigned int length, unsigned int buffersize);
 };
 
 #endif //__AUD_FILEWRITER_H__
index 2e07417154b85828ea822c048628ab834ff940d0..0c9f02c0155d86452e99176976f8bd52234a266c 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <map>
 #include <cstddef>
+#include <pthread.h>
 
 // #define MEM_DEBUG
 
@@ -49,8 +50,13 @@ private:
         * Saves the reference counts.
         */
        static std::map<void*, unsigned int> m_references;
+       static pthread_mutex_t m_mutex;
+       static bool m_mutex_initialised;
 
 public:
+
+       static pthread_mutex_t* getMutex();
+
        /**
         * Reference increment.
         * \param reference The reference.
@@ -108,6 +114,7 @@ public:
        template <class U>
        AUD_Reference(U* reference)
        {
+               pthread_mutex_lock(AUD_ReferenceHandler::getMutex());
                m_original = reference;
                m_reference = dynamic_cast<T*>(reference);
                AUD_ReferenceHandler::incref(m_original);
@@ -115,6 +122,7 @@ public:
                if(m_reference != NULL)
                        std::cerr << "+" << typeid(*m_reference).name() << std::endl;
 #endif
+               pthread_mutex_unlock(AUD_ReferenceHandler::getMutex());
        }
 
        AUD_Reference()
@@ -129,6 +137,7 @@ public:
         */
        AUD_Reference(const AUD_Reference& ref)
        {
+               pthread_mutex_lock(AUD_ReferenceHandler::getMutex());
                m_original = ref.m_original;
                m_reference = ref.m_reference;
                AUD_ReferenceHandler::incref(m_original);
@@ -136,11 +145,13 @@ public:
                if(m_reference != NULL)
                        std::cerr << "+" << typeid(*m_reference).name() << std::endl;
 #endif
+               pthread_mutex_unlock(AUD_ReferenceHandler::getMutex());
        }
 
        template <class U>
        explicit AUD_Reference(const AUD_Reference<U>& ref)
        {
+               pthread_mutex_lock(AUD_ReferenceHandler::getMutex());
                m_original = ref.get();
                m_reference = dynamic_cast<T*>(ref.get());
                AUD_ReferenceHandler::incref(m_original);
@@ -148,6 +159,7 @@ public:
                if(m_reference != NULL)
                        std::cerr << "+" << typeid(*m_reference).name() << std::endl;
 #endif
+               pthread_mutex_unlock(AUD_ReferenceHandler::getMutex());
        }
 
        /**
@@ -156,12 +168,14 @@ public:
         */
        ~AUD_Reference()
        {
+               pthread_mutex_lock(AUD_ReferenceHandler::getMutex());
 #ifdef MEM_DEBUG
                if(m_reference != NULL)
                        std::cerr << "-" << typeid(*m_reference).name() << std::endl;
 #endif
                if(AUD_ReferenceHandler::decref(m_original))
                        delete m_reference;
+               pthread_mutex_unlock(AUD_ReferenceHandler::getMutex());
        }
 
        /**
@@ -173,6 +187,8 @@ public:
                if(&ref == this)
                        return *this;
 
+               pthread_mutex_lock(AUD_ReferenceHandler::getMutex());
+
 #ifdef MEM_DEBUG
                if(m_reference != NULL)
                        std::cerr << "-" << typeid(*m_reference).name() << std::endl;
@@ -188,6 +204,8 @@ public:
                        std::cerr << "+" << typeid(*m_reference).name() << std::endl;
 #endif
 
+               pthread_mutex_unlock(AUD_ReferenceHandler::getMutex());
+
                return *this;
        }
 
index 24f645df76100a298615eb568ae8ace5314ce2b8..3e9f6707262daab08cba9bc36e788c58070cd068 100644 (file)
 #include "AUD_Reference.h"
 
 std::map<void*, unsigned int> AUD_ReferenceHandler::m_references;
+pthread_mutex_t AUD_ReferenceHandler::m_mutex;
+bool AUD_ReferenceHandler::m_mutex_initialised = false;
+
+pthread_mutex_t *AUD_ReferenceHandler::getMutex()
+{
+       if(!m_mutex_initialised)
+       {
+               pthread_mutexattr_t attr;
+               pthread_mutexattr_init(&attr);
+               pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+
+               pthread_mutex_init(&m_mutex, &attr);
+
+               pthread_mutexattr_destroy(&attr);
+
+               m_mutex_initialised = true;
+       }
+
+       return &m_mutex;
+}
+
index 8b6d84337c2b51019148fa0f160adf4e177e7efd..9557821d642786f467c629ee0100da7e93ff48fc 100644 (file)
@@ -63,7 +63,7 @@ public:
                for (int i = 0; i < m_num_buckets; ++i) {
                        m_buckets[i] = 0;
 
-                       for(Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next)
+                       for (Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next)
                                insert(entry->m_key, entry->m_value);
                }
        }
index cb99ea3b499d49df4c7154e29795ac006ba234c9..35f97bf629f42e303f60059709f273de485a440c 100644 (file)
@@ -85,10 +85,10 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
                 description="Leave out caustics, resulting in a darker image with less noise",
                 default=False,
                 )
-        cls.blur_caustics = FloatProperty(
-                name="Blur Caustics",
-                description="Blur caustics to reduce noise",
-                min=0.0, max=1.0,
+        cls.blur_glossy = FloatProperty(
+                name="Filter Glossy",
+                description="Adaptively blur glossy shaders after blurry bounces, to reduce noise at the cost of accuracy",
+                min=0.0, max=10.0,
                 default=0.0,
                 )
 
index 624d00b377dcd07888707cab40d9078fa6b05a76..0ed08589327a77a90a25ff6385887704fb95a474 100644 (file)
@@ -87,11 +87,11 @@ class CyclesRender_PT_integrator(CyclesButtonsPanel, Panel):
         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
         sub.prop(cscene, "glossy_bounces", text="Glossy")
         sub.prop(cscene, "transmission_bounces", text="Transmission")
-        sub.prop(cscene, "no_caustics")
 
-        #row = col.row()
-        #row.prop(cscene, "blur_caustics")
-        #row.active = not cscene.no_caustics
+        col.separator()
+
+        col.prop(cscene, "no_caustics")
+        col.prop(cscene, "blur_glossy")
 
 
 class CyclesRender_PT_film(CyclesButtonsPanel, Panel):
@@ -178,10 +178,7 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
 
         col = split.column()
         col.prop(scene, "layers", text="Scene")
-        col.label(text="Material:")
-        col.prop(rl, "material_override", text="")
-
-        col.prop(rl, "use_sky", "Use Environment")
+        col.prop(rl, "layers_exclude", text="Exclude")
 
         col = split.column()
         col.prop(rl, "layers", text="Layer")
@@ -190,6 +187,16 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
 
         split = layout.split()
 
+        col = split.column()
+        col.label(text="Material:")
+        col.prop(rl, "material_override", text="")
+
+        col = split.column()
+        col.prop(rl, "samples")
+        col.prop(rl, "use_sky", "Use Environment")
+
+        split = layout.split()
+
         col = split.column()
         col.label(text="Passes:")
         col.prop(rl, "use_pass_combined")
index dc6c69e29042167046bb4993cc80ee65eaf8f261..5ece7aa26e205d8953028a2add9eb067a78be781 100644 (file)
@@ -218,12 +218,13 @@ void BlenderSession::render()
                scene->film->passes = passes;
                scene->film->tag_update(scene);
 
-               /* update session */
-               session->reset(buffer_params, session_params.samples);
-
                /* update scene */
                sync->sync_data(b_v3d, b_iter->name().c_str());
 
+               /* update session */
+               int samples = sync->get_layer_samples();
+               session->reset(buffer_params, (samples == 0)? session_params.samples: samples);
+
                /* render */
                session->start();
                session->wait();
index 5a28629877441efc83fd9874ad7d7f26dd2863b5..41cd200d0031ea234a1cfb04c0409a53f836cdb0 100644 (file)
@@ -153,6 +153,8 @@ void BlenderSync::sync_integrator()
        integrator->transparent_shadows = get_boolean(cscene, "use_transparent_shadows");
 
        integrator->no_caustics = get_boolean(cscene, "no_caustics");
+       integrator->filter_glossy = get_float(cscene, "blur_glossy");
+
        integrator->seed = get_int(cscene, "seed");
 
        integrator->layer_flag = render_layer.layer;
@@ -208,6 +210,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
                        render_layer.holdout_layer = 0;
                        render_layer.material_override = PointerRNA_NULL;
                        render_layer.use_background = true;
+                       render_layer.samples = 0;
                        return;
                }
        }
@@ -220,12 +223,13 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
        for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) {
                if((!layer && first_layer) || (layer && b_rlay->name() == layer)) {
                        render_layer.name = b_rlay->name();
-                       render_layer.scene_layer = get_layer(b_scene.layers());
+                       render_layer.scene_layer = get_layer(b_scene.layers()) & ~get_layer(b_rlay->layers_exclude());
                        render_layer.layer = get_layer(b_rlay->layers());
                        render_layer.holdout_layer = get_layer(b_rlay->layers_zmask());
                        render_layer.layer |= render_layer.holdout_layer;
                        render_layer.material_override = b_rlay->material_override();
                        render_layer.use_background = b_rlay->use_sky();
+                       render_layer.samples = b_rlay->samples();
                }
 
                first_layer = false;
index d2550a1ffd7150bd77276aa320f504edccf773d9..ab8e4bd8d00afa7486a515d37c69c5b9c3bfa4b8 100644 (file)
@@ -57,6 +57,7 @@ public:
        void sync_data(BL::SpaceView3D b_v3d, const char *layer = 0);
        void sync_camera(BL::Object b_override, int width, int height);
        void sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height);
+       int get_layer_samples() { return render_layer.samples; }
 
        /* get parameters */
        static SceneParams get_scene_params(BL::Scene b_scene, bool background);
@@ -108,7 +109,8 @@ private:
                RenderLayerInfo()
                : scene_layer(0), layer(0), holdout_layer(0),
                  material_override(PointerRNA_NULL),
-                 use_background(true)
+                 use_background(true),
+                 samples(0)
                {}
 
                string name;
@@ -117,6 +119,7 @@ private:
                uint holdout_layer;
                BL::Material material_override;
                bool use_background;
+               int samples;
        } render_layer;
 };
 
index decc576fe51e393c3874317c5d58a48b7cd4feae..131a7a1f750f7545ce9d36ead0063c90200c7923 100644 (file)
@@ -10,17 +10,21 @@ set(INC
 
 set(SRC
        bvh.cpp
+       bvh_binning.cpp
        bvh_build.cpp
        bvh_node.cpp
        bvh_sort.cpp
+       bvh_split.cpp
 )
 
 set(SRC_HEADERS
        bvh.h
+       bvh_binning.h
        bvh_build.h
        bvh_node.h
        bvh_params.h
        bvh_sort.h
+       bvh_split.h
 )
 
 include_directories(${INC})
index c9bfa9643322e7d09dd7617ff0e651622083c375..15695dddf459f2580ced4716d587d366a43c8c0c 100644 (file)
@@ -530,7 +530,7 @@ void RegularBVH::refit_nodes()
 {
        assert(!params.top_level);
 
-       BoundBox bbox;
+       BoundBox bbox = BoundBox::empty;
        uint visibility = 0;
        refit_node(0, (pack.is_leaf[0])? true: false, bbox, visibility);
 }
@@ -572,7 +572,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
        }
        else {
                /* refit inner node, set bbox from children */
-               BoundBox bbox0, bbox1;
+               BoundBox bbox0 = BoundBox::empty, bbox1 = BoundBox::empty;
                uint visibility0 = 0, visibility1 = 0;
 
                refit_node((c0 < 0)? -c0-1: c0, (c0 < 0), bbox0, visibility0);
index 38674c2c5611da943387111de49ca47a7bc82ea3..c5b4f1d01ae94468ca4e99784d6856723d26f74a 100644 (file)
  * limitations under the License.
  */
 
+#include "bvh_binning.h"
 #include "bvh_build.h"
 #include "bvh_node.h"
 #include "bvh_params.h"
-#include "bvh_sort.h"
+#include "bvh_split.h"
 
 #include "mesh.h"
 #include "object.h"
 #include "scene.h"
 
-#include "util_algorithm.h"
+#include "util_debug.h"
 #include "util_foreach.h"
 #include "util_progress.h"
 #include "util_time.h"
 
 CCL_NAMESPACE_BEGIN
 
+/* BVH Build Task */
+
+class BVHBuildTask : public Task {
+public:
+       BVHBuildTask(InnerNode *node_, int child_, BVHObjectBinning& range_, int level_)
+       : node(node_), child(child_), level(level_), range(range_) {}
+
+       InnerNode *node;
+       int child;
+       int level;
+       BVHObjectBinning range;
+};
+
 /* Constructor / Destructor */
 
 BVHBuild::BVHBuild(const vector<Object*>& objects_,
@@ -41,10 +55,10 @@ BVHBuild::BVHBuild(const vector<Object*>& objects_,
   prim_object(prim_object_),
   params(params_),
   progress(progress_),
-  progress_start_time(0.0)
+  progress_start_time(0.0),
+  task_pool(function_bind(&BVHBuild::thread_build_node, this, _1, _2))
 {
        spatial_min_overlap = 0.0f;
-       progress_num_duplicates = 0;
 }
 
 BVHBuild::~BVHBuild()
@@ -53,57 +67,63 @@ BVHBuild::~BVHBuild()
 
 /* Adding References */
 
-void BVHBuild::add_reference_mesh(NodeSpec& root, Mesh *mesh, int i)
+void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i)
 {
        for(uint j = 0; j < mesh->triangles.size(); j++) {
                Mesh::Triangle t = mesh->triangles[j];
-               Reference ref;
+               BoundBox bounds = BoundBox::empty;
 
                for(int k = 0; k < 3; k++) {
                        float3 pt = mesh->verts[t.v[k]];
-                       ref.bounds.grow(pt);
+                       bounds.grow(pt);
                }
 
-               if(ref.bounds.valid()) {
-                       ref.prim_index = j;
-                       ref.prim_object = i;
-
-                       references.push_back(ref);
-                       root.bounds.grow(ref.bounds);
+               if(bounds.valid()) {
+                       references.push_back(BVHReference(bounds, j, i));
+                       root.grow(bounds);
+                       center.grow(bounds.center2());
                }
        }
 }
 
-void BVHBuild::add_reference_object(NodeSpec& root, Object *ob, int i)
+void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i)
 {
-       Reference ref;
-
-       ref.prim_index = -1;
-       ref.prim_object = i;
-       ref.bounds = ob->bounds;
-
-       references.push_back(ref);
-       root.bounds.grow(ref.bounds);
+       references.push_back(BVHReference(ob->bounds, -1, i));
+       root.grow(ob->bounds);
+       center.grow(ob->bounds.center2());
 }
 
-void BVHBuild::add_references(NodeSpec& root)
+void BVHBuild::add_references(BVHRange& root)
 {
-       /* init root spec */
-       root.num = 0;
-       root.bounds = BoundBox();
+       /* reserve space for references */
+       size_t num_alloc_references = 0;
+
+       foreach(Object *ob, objects) {
+               if(params.top_level) {
+                       if(ob->mesh->transform_applied)
+                               num_alloc_references += ob->mesh->triangles.size();
+                       else
+                               num_alloc_references++;
+               }
+               else
+                       num_alloc_references += ob->mesh->triangles.size();
+       }
+
+       references.reserve(num_alloc_references);
 
-       /* add objects */
+       /* add references from objects */
+       BoundBox bounds = BoundBox::empty, center = BoundBox::empty;
        int i = 0;
 
        foreach(Object *ob, objects) {
                if(params.top_level) {
                        if(ob->mesh->transform_applied)
-                               add_reference_mesh(root, ob->mesh, i);
+                               add_reference_mesh(bounds, center, ob->mesh, i);
                        else
-                               add_reference_object(root, ob, i);
+                               add_reference_object(bounds, center, ob, i);
                }
                else
-                       add_reference_mesh(root, ob->mesh, i);
+                       add_reference_mesh(bounds, center, ob->mesh, i);
 
                i++;
 
@@ -111,129 +131,213 @@ void BVHBuild::add_references(NodeSpec& root)
        }
 
        /* happens mostly on empty meshes */
-       if(!root.bounds.valid())
-               root.bounds.grow(make_float3(0.0f, 0.0f, 0.0f));
+       if(!bounds.valid())
+               bounds.grow(make_float3(0.0f, 0.0f, 0.0f));
 
-       root.num = references.size();
+       root = BVHRange(bounds, center, 0, references.size());
 }
 
 /* Build */
 
 BVHNode* BVHBuild::run()
 {
-       NodeSpec root;
+       BVHRange root;
 
        /* add references */
        add_references(root);
 
-       if(progress.get_cancel()) return NULL;
+       if(progress.get_cancel())
+               return NULL;
 
        /* init spatial splits */
        if(params.top_level) /* todo: get rid of this */
                params.use_spatial_split = false;
 
-       spatial_min_overlap = root.bounds.area() * params.spatial_split_alpha;
+       spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha;
        spatial_right_bounds.clear();
-       spatial_right_bounds.resize(max(root.num, (int)BVHParams::NUM_SPATIAL_BINS) - 1);
+       spatial_right_bounds.resize(max(root.size(), (int)BVHParams::NUM_SPATIAL_BINS) - 1);
 
        /* init progress updates */
-       progress_num_duplicates = 0;
        progress_start_time = time_dt();
+       progress_count = 0;
+       progress_total = references.size();
+       progress_original_total = progress_total;
+
+       prim_index.resize(references.size());
+       prim_object.resize(references.size());
 
        /* build recursively */
-       return build_node(root, 0, 0.0f, 1.0f);
+       BVHNode *rootnode;
+
+       if(params.use_spatial_split) {
+               /* singlethreaded spatial split build */
+               rootnode = build_node(root, 0);
+       }
+       else {
+               /* multithreaded binning build */
+               BVHObjectBinning rootbin(root, &references[0]);
+               rootnode = build_node(rootbin, 0);
+               task_pool.wait();
+       }
+
+       /* delete if we cancelled */
+       if(rootnode) {
+               if(progress.get_cancel()) {
+                       rootnode->deleteSubtree();
+                       rootnode = NULL;
+               }
+               else if(!params.use_spatial_split) {
+                       /*rotate(rootnode, 4, 5);*/
+                       rootnode->update_visibility();
+               }
+       }
+
+       return rootnode;
 }
 
-void BVHBuild::progress_update(float progress_start, float progress_end)
+void BVHBuild::progress_update()
 {
        if(time_dt() - progress_start_time < 0.25f)
                return;
+       
+       double progress_start = (double)progress_count/(double)progress_total;
+       double duplicates = (double)(progress_total - progress_original_total)/(double)progress_total;
 
-       float duplicates = (float)progress_num_duplicates/(float)references.size();
        string msg = string_printf("Building BVH %.0f%%, duplicates %.0f%%",
                progress_start*100.0f, duplicates*100.0f);
 
        progress.set_substatus(msg);
-       progress_start_time = time_dt();
+       progress_start_time = time_dt(); 
 }
 
-BVHNode* BVHBuild::build_node(const NodeSpec& spec, int level, float progress_start, float progress_end)
+void BVHBuild::thread_build_node(Task *task_, int thread_id)
 {
-       /* progress update */
-       progress_update(progress_start, progress_end);
-       if(progress.get_cancel()) return NULL;
+       if(progress.get_cancel())
+               return;
 
-       /* small enough or too deep => create leaf. */
-       if(spec.num <= params.min_leaf_size || level >= BVHParams::MAX_DEPTH)
-               return create_leaf_node(spec);
-
-       /* find split candidates. */
-       float area = spec.bounds.area();
-       float leafSAH = area * params.triangle_cost(spec.num);
-       float nodeSAH = area * params.node_cost(2);
-       ObjectSplit object = find_object_split(spec, nodeSAH);
-       SpatialSplit spatial;
-
-       if(params.use_spatial_split && level < BVHParams::MAX_SPATIAL_DEPTH) {
-               BoundBox overlap = object.left_bounds;
-               overlap.intersect(object.right_bounds);
-
-               if(overlap.area() >= spatial_min_overlap)
-                       spatial = find_spatial_split(spec, nodeSAH);
-       }
+       /* build nodes */
+       BVHBuildTask *task = (BVHBuildTask*)task_;
+       BVHNode *node = build_node(task->range, task->level);
+
+       /* set child in inner node */
+       task->node->children[task->child] = node;
 
-       /* leaf SAH is the lowest => create leaf. */
-       float minSAH = min(min(leafSAH, object.sah), spatial.sah);
+       /* update progress */
+       if(task->range.size() < THREAD_TASK_SIZE) {
+               /*rotate(node, INT_MAX, 5);*/
 
-       if(minSAH == leafSAH && spec.num <= params.max_leaf_size)
-               return create_leaf_node(spec);
+               thread_scoped_lock lock(build_mutex);
 
-       /* perform split. */
-       NodeSpec left, right;
+               progress_count += task->range.size();
+               progress_update();
+       }
+}
+
+/* multithreaded binning builder */
+BVHNode* BVHBuild::build_node(const BVHObjectBinning& range, int level)
+{
+       size_t size = range.size();
+       float leafSAH = params.sah_triangle_cost * range.leafSAH;
+       float splitSAH = params.sah_node_cost * range.bounds().half_area() + params.sah_triangle_cost * range.splitSAH;
 
-       if(params.use_spatial_split && minSAH == spatial.sah)
-               do_spatial_split(left, right, spec, spatial);
-       if(!left.num || !right.num)
-               do_object_split(left, right, spec, object);
+       /* make leaf node when threshold reached or SAH tells us */
+       if(params.small_enough_for_leaf(size, level) || (size <= params.max_leaf_size && leafSAH < splitSAH))
+               return create_leaf_node(range);
+
+       /* perform split */
+       BVHObjectBinning left, right;
+       range.split(&references[0], left, right);
 
        /* create inner node. */
-       progress_num_duplicates += left.num + right.num - spec.num;
+       InnerNode *inner;
 
-       float progress_mid = lerp(progress_start, progress_end, (float)right.num / (float)(left.num + right.num));
+       if(range.size() < THREAD_TASK_SIZE) {
+               /* local build */
+               BVHNode *leftnode = build_node(left, level + 1);
+               BVHNode *rightnode = build_node(right, level + 1);
 
-       BVHNode* rightNode = build_node(right, level + 1, progress_start, progress_mid);
-       if(progress.get_cancel()) {
-               if(rightNode) rightNode->deleteSubtree();
-               return NULL;
+               inner = new InnerNode(range.bounds(), leftnode, rightnode);
        }
+       else {
+               /* threaded build */
+               inner = new InnerNode(range.bounds());
+
+               task_pool.push(new BVHBuildTask(inner, 0, left, level + 1), true);
+               task_pool.push(new BVHBuildTask(inner, 1, right, level + 1), true);
+       }
+
+       return inner;
+}
 
-       BVHNode* leftNode = build_node(left, level + 1, progress_mid, progress_end);
-       if(progress.get_cancel()) {
-               if(leftNode) leftNode->deleteSubtree();
+/* single threaded spatial split builder */
+BVHNode* BVHBuild::build_node(const BVHRange& range, int level)
+{
+       /* progress update */
+       progress_update();
+       if(progress.get_cancel())
                return NULL;
+
+       /* small enough or too deep => create leaf. */
+       if(params.small_enough_for_leaf(range.size(), level)) {
+               progress_count += range.size();
+               return create_leaf_node(range);
+       }
+
+       /* splitting test */
+       BVHMixedSplit split(this, range, level);
+
+       if(split.no_split) {
+               progress_count += range.size();
+               return create_leaf_node(range);
        }
+       
+       /* do split */
+       BVHRange left, right;
+       split.split(this, left, right, range);
+
+       progress_total += left.size() + right.size() - range.size();
+       size_t total = progress_total;
+
+       /* leaft node */
+       BVHNode *leftnode = build_node(left, level + 1);
+
+       /* right node (modify start for splits) */
+       right.set_start(right.start() + progress_total - total);
+       BVHNode *rightnode = build_node(right, level + 1);
 
-       return new InnerNode(spec.bounds, leftNode, rightNode);
+       /* inner node */
+       return new InnerNode(range.bounds(), leftnode, rightnode);
 }
 
-BVHNode *BVHBuild::create_object_leaf_nodes(const Reference *ref, int num)
+/* Create Nodes */
+
+BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start, int num)
 {
        if(num == 0) {
-               BoundBox bounds;
+               BoundBox bounds = BoundBox::empty;
                return new LeafNode(bounds, 0, 0, 0);
        }
        else if(num == 1) {
-               prim_index.push_back(ref[0].prim_index);
-               prim_object.push_back(ref[0].prim_object);
-               uint visibility = objects[ref[0].prim_object]->visibility;
-               return new LeafNode(ref[0].bounds, visibility, prim_index.size()-1, prim_index.size());
+               if(start == prim_index.size()) {
+                       assert(params.use_spatial_split);
+
+                       prim_index.push_back(ref->prim_index());
+                       prim_object.push_back(ref->prim_object());
+               }
+               else {
+                       prim_index[start] = ref->prim_index();
+                       prim_object[start] = ref->prim_object();
+               }
+
+               uint visibility = objects[ref->prim_object()]->visibility;
+               return new LeafNode(ref->bounds(), visibility, start, start+1);
        }
        else {
                int mid = num/2;
-               BVHNode *leaf0 = create_object_leaf_nodes(ref, mid); 
-               BVHNode *leaf1 = create_object_leaf_nodes(ref+mid, num-mid); 
+               BVHNode *leaf0 = create_object_leaf_nodes(ref, start, mid); 
+               BVHNode *leaf1 = create_object_leaf_nodes(ref+mid, start+mid, num-mid); 
 
-               BoundBox bounds;
+               BoundBox bounds = BoundBox::empty;
                bounds.grow(leaf0->m_bounds);
                bounds.grow(leaf1->m_bounds);
 
@@ -241,310 +345,136 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const Reference *ref, int num)
        }
 }
 
-BVHNode* BVHBuild::create_leaf_node(const NodeSpec& spec)
+BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
 {
        vector<int>& p_index = prim_index;
        vector<int>& p_object = prim_object;
-       BoundBox bounds;
-       int num = 0;
+       BoundBox bounds = BoundBox::empty;
+       int num = 0, ob_num = 0;
        uint visibility = 0;
 
-       for(int i = 0; i < spec.num; i++) {
-               if(references.back().prim_index != -1) {
-                       p_index.push_back(references.back().prim_index);
-                       p_object.push_back(references.back().prim_object);
-                       bounds.grow(references.back().bounds);
-                       visibility |= objects[references.back().prim_object]->visibility;
-                       references.pop_back();
+       for(int i = 0; i < range.size(); i++) {
+               BVHReference& ref = references[range.start() + i];
+
+               if(ref.prim_index() != -1) {
+                       if(range.start() + num == prim_index.size()) {
+                               assert(params.use_spatial_split);
+
+                               p_index.push_back(ref.prim_index());
+                               p_object.push_back(ref.prim_object());
+                       }
+                       else {
+                               p_index[range.start() + num] = ref.prim_index();
+                               p_object[range.start() + num] = ref.prim_object();
+                       }
+
+                       bounds.grow(ref.bounds());
+                       visibility |= objects[ref.prim_object()]->visibility;
                        num++;
                }
+               else {
+                       if(ob_num < i)
+                               references[range.start() + ob_num] = ref;
+                       ob_num++;
+               }
        }
 
        BVHNode *leaf = NULL;
        
        if(num > 0) {
-               leaf = new LeafNode(bounds, visibility, p_index.size() - num, p_index.size());
+               leaf = new LeafNode(bounds, visibility, range.start(), range.start() + num);
 
-               if(num == spec.num)
+               if(num == range.size())
                        return leaf;
        }
 
        /* while there may be multiple triangles in a leaf, for object primitives
-        * we want them to be the only one, so we  */
-       int ob_num = spec.num - num;
-       const Reference *ref = (ob_num)? &references.back() - (ob_num - 1): NULL;
-       BVHNode *oleaf = create_object_leaf_nodes(ref, ob_num);
-       for(int i = 0; i < ob_num; i++)
-               references.pop_back();
+        * we want there to be the only one, so we keep splitting */
+       const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
+       BVHNode *oleaf = create_object_leaf_nodes(ref, range.start() + num, ob_num);
        
        if(leaf)
-               return new InnerNode(spec.bounds, leaf, oleaf);
+               return new InnerNode(range.bounds(), leaf, oleaf);
        else
                return oleaf;
 }
 
-/* Object Split */
+/* Tree Rotations */
 
-BVHBuild::ObjectSplit BVHBuild::find_object_split(const NodeSpec& spec, float nodeSAH)
+void BVHBuild::rotate(BVHNode *node, int max_depth, int iterations)
 {
-       ObjectSplit split;
-       const Reference *ref_ptr = &references[references.size() - spec.num];
-
-       for(int dim = 0; dim < 3; dim++) {
-               /* sort references */
-               bvh_reference_sort(references.size() - spec.num, references.size(), &references[0], dim);
-
-               /* sweep right to left and determine bounds. */
-               BoundBox right_bounds;
-
-               for(int i = spec.num - 1; i > 0; i--) {
-                       right_bounds.grow(ref_ptr[i].bounds);
-                       spatial_right_bounds[i - 1] = right_bounds;
-               }
-
-               /* sweep left to right and select lowest SAH. */
-               BoundBox left_bounds;
-
-               for(int i = 1; i < spec.num; i++) {
-                       left_bounds.grow(ref_ptr[i - 1].bounds);
-                       right_bounds = spatial_right_bounds[i - 1];
-
-                       float sah = nodeSAH +
-                               left_bounds.area() * params.triangle_cost(i) +
-                               right_bounds.area() * params.triangle_cost(spec.num - i);
-
-                       if(sah < split.sah) {
-                               split.sah = sah;
-                               split.dim = dim;
-                               split.num_left = i;
-                               split.left_bounds = left_bounds;
-                               split.right_bounds = right_bounds;
-                       }
-               }
-       }
-
-       return split;
+       /* in tested scenes, this resulted in slightly slower raytracing, so disabled
+        * it for now. could be implementation bug, or depend on the scene */
+       if(node)
+               for(int i = 0; i < iterations; i++)
+                       rotate(node, max_depth);
 }
 
-void BVHBuild::do_object_split(NodeSpec& left, NodeSpec& right, const NodeSpec& spec, const ObjectSplit& split)
+void BVHBuild::rotate(BVHNode *node, int max_depth)
 {
-       /* sort references according to split */
-       int start = references.size() - spec.num;
-       int end = references.size(); /* todo: is this right? */
-
-       bvh_reference_sort(start, end, &references[0], split.dim);
-
-       /* split node specs */
-       left.num = split.num_left;
-       left.bounds = split.left_bounds;
-       right.num = spec.num - split.num_left;
-       right.bounds = split.right_bounds;
-}
-
-/* Spatial Split */
-
-BVHBuild::SpatialSplit BVHBuild::find_spatial_split(const NodeSpec& spec, float nodeSAH)
-{
-       /* initialize bins. */
-       float3 origin = spec.bounds.min;
-       float3 binSize = (spec.bounds.max - origin) * (1.0f / (float)BVHParams::NUM_SPATIAL_BINS);
-       float3 invBinSize = 1.0f / binSize;
-
-       for(int dim = 0; dim < 3; dim++) {
-               for(int i = 0; i < BVHParams::NUM_SPATIAL_BINS; i++) {
-                       SpatialBin& bin = spatial_bins[dim][i];
-
-                       bin.bounds = BoundBox();
-                       bin.enter = 0;
-                       bin.exit = 0;
-               }
-       }
-
-       /* chop references into bins. */
-       for(unsigned int refIdx = references.size() - spec.num; refIdx < references.size(); refIdx++) {
-               const Reference& ref = references[refIdx];
-               float3 firstBinf = (ref.bounds.min - origin) * invBinSize;
-               float3 lastBinf = (ref.bounds.max - origin) * invBinSize;
-               int3 firstBin = make_int3((int)firstBinf.x, (int)firstBinf.y, (int)firstBinf.z);
-               int3 lastBin = make_int3((int)lastBinf.x, (int)lastBinf.y, (int)lastBinf.z);
+       /* nothing to rotate if we reached a leaf node. */
+       if(node->is_leaf() || max_depth < 0)
+               return;
+       
+       InnerNode *parent = (InnerNode*)node;
 
-               firstBin = clamp(firstBin, 0, BVHParams::NUM_SPATIAL_BINS - 1);
-               lastBin = clamp(lastBin, firstBin, BVHParams::NUM_SPATIAL_BINS - 1);
+       /* rotate all children first */
+       for(size_t c = 0; c < 2; c++)
+               rotate(parent->children[c], max_depth-1);
 
-               for(int dim = 0; dim < 3; dim++) {
-                       Reference currRef = ref;
+       /* compute current area of all children */
+       BoundBox bounds0 = parent->children[0]->m_bounds;
+       BoundBox bounds1 = parent->children[1]->m_bounds;
 
-                       for(int i = firstBin[dim]; i < lastBin[dim]; i++) {
-                               Reference leftRef, rightRef;
+       float area0 = bounds0.half_area();
+       float area1 = bounds1.half_area();
+       float4 child_area = make_float4(area0, area1, 0.0f, 0.0f);
 
-                               split_reference(leftRef, rightRef, currRef, dim, origin[dim] + binSize[dim] * (float)(i + 1));
-                               spatial_bins[dim][i].bounds.grow(leftRef.bounds);
-                               currRef = rightRef;
-                       }
+       /* find best rotation. we pick a target child of a first child, and swap
+        * this with an other child. we perform the best such swap. */
+       float best_cost = FLT_MAX;
+       int best_child = -1, bets_target = -1, best_other = -1;
 
-                       spatial_bins[dim][lastBin[dim]].bounds.grow(currRef.bounds);
-                       spatial_bins[dim][firstBin[dim]].enter++;
-                       spatial_bins[dim][lastBin[dim]].exit++;
-               }
-       }
+       for(size_t c = 0; c < 2; c++) {
+               /* ignore leaf nodes as we cannot descent into */
+               if(parent->children[c]->is_leaf())
+                       continue;
 
-       /* select best split plane. */
-       SpatialSplit split;
+               InnerNode *child = (InnerNode*)parent->children[c];
+               BoundBox& other = (c == 0)? bounds1: bounds0;
 
-       for(int dim = 0; dim < 3; dim++) {
-               /* sweep right to left and determine bounds. */
-               BoundBox right_bounds;
+               /* transpose child bounds */
+               BoundBox target0 = child->children[0]->m_bounds;
+               BoundBox target1 = child->children[1]->m_bounds;
 
-               for(int i = BVHParams::NUM_SPATIAL_BINS - 1; i > 0; i--) {
-                       right_bounds.grow(spatial_bins[dim][i].bounds);
-                       spatial_right_bounds[i - 1] = right_bounds;
-               }
+               /* compute cost for both possible swaps */
+               float cost0 = merge(other, target1).half_area() - child_area[c];
+               float cost1 = merge(target0, other).half_area() - child_area[c];
 
-               /* sweep left to right and select lowest SAH. */
-               BoundBox left_bounds;
-               int leftNum = 0;
-               int rightNum = spec.num;
+               if(min(cost0,cost1) < best_cost) {
+                       best_child = (int)c;
+                       best_other = (int)(1-c);
 
-               for(int i = 1; i < BVHParams::NUM_SPATIAL_BINS; i++) {
-                       left_bounds.grow(spatial_bins[dim][i - 1].bounds);
-                       leftNum += spatial_bins[dim][i - 1].enter;
-                       rightNum -= spatial_bins[dim][i - 1].exit;
-
-                       float sah = nodeSAH +
-                               left_bounds.area() * params.triangle_cost(leftNum) +
-                               spatial_right_bounds[i - 1].area() * params.triangle_cost(rightNum);
-
-                       if(sah < split.sah) {
-                               split.sah = sah;
-                               split.dim = dim;
-                               split.pos = origin[dim] + binSize[dim] * (float)i;
+                       if(cost0 < cost1) {
+                               best_cost = cost0;
+                               bets_target = 0;
+                       }
+                       else {
+                               best_cost = cost0;
+                               bets_target = 1;
                        }
                }
        }
 
-       return split;
-}
-
-void BVHBuild::do_spatial_split(NodeSpec& left, NodeSpec& right, const NodeSpec& spec, const SpatialSplit& split)
-{
-       /* Categorize references and compute bounds.
-        *
-        * Left-hand side:                      [left_start, left_end[
-        * Uncategorized/split:         [left_end, right_start[
-        * Right-hand side:                     [right_start, refs.size()[ */
-
-       vector<Reference>& refs = references;
-       int left_start = refs.size() - spec.num;
-       int left_end = left_start;
-       int right_start = refs.size();
-
-       left.bounds = right.bounds = BoundBox();
-
-       for(int i = left_end; i < right_start; i++) {
-               if(refs[i].bounds.max[split.dim] <= split.pos) {
-                       /* entirely on the left-hand side */
-                       left.bounds.grow(refs[i].bounds);
-                       swap(refs[i], refs[left_end++]);
-               }
-               else if(refs[i].bounds.min[split.dim] >= split.pos) {
-                       /* entirely on the right-hand side */
-                       right.bounds.grow(refs[i].bounds);
-                       swap(refs[i--], refs[--right_start]);
-               }
-       }
-
-       /* duplicate or unsplit references intersecting both sides. */
-       while(left_end < right_start) {
-               /* split reference. */
-               Reference lref, rref;
-
-               split_reference(lref, rref, refs[left_end], split.dim, split.pos);
-
-               /* compute SAH for duplicate/unsplit candidates. */
-               BoundBox lub = left.bounds;             // Unsplit to left:             new left-hand bounds.
-               BoundBox rub = right.bounds;    // Unsplit to right:    new right-hand bounds.
-               BoundBox ldb = left.bounds;             // Duplicate:                   new left-hand bounds.
-               BoundBox rdb = right.bounds;    // Duplicate:                   new right-hand bounds.
-
-               lub.grow(refs[left_end].bounds);
-               rub.grow(refs[left_end].bounds);
-               ldb.grow(lref.bounds);
-               rdb.grow(rref.bounds);
-
-               float lac = params.triangle_cost(left_end - left_start);
-               float rac = params.triangle_cost(refs.size() - right_start);
-               float lbc = params.triangle_cost(left_end - left_start + 1);
-               float rbc = params.triangle_cost(refs.size() - right_start + 1);
-
-               float unsplitLeftSAH = lub.area() * lbc + right.bounds.area() * rac;
-               float unsplitRightSAH = left.bounds.area() * lac + rub.area() * rbc;
-               float duplicateSAH = ldb.area() * lbc + rdb.area() * rbc;
-               float minSAH = min(min(unsplitLeftSAH, unsplitRightSAH), duplicateSAH);
-
-               if(minSAH == unsplitLeftSAH) {
-                       /* unsplit to left */
-                       left.bounds = lub;
-                       left_end++;
-               }
-               else if(minSAH == unsplitRightSAH) {
-                       /* unsplit to right */
-                       right.bounds = rub;
-                       swap(refs[left_end], refs[--right_start]);
-               }
-               else {
-                       /* duplicate */
-                       left.bounds = ldb;
-                       right.bounds = rdb;
-                       refs[left_end++] = lref;
-                       refs.push_back(rref);
-               }
-       }
-
-       left.num = left_end - left_start;
-       right.num = refs.size() - right_start;
-}
+       /* if we did not find a swap that improves the SAH then do nothing */
+       if(best_cost >= 0)
+               return;
 
-void BVHBuild::split_reference(Reference& left, Reference& right, const Reference& ref, int dim, float pos)
-{
-       /* initialize references. */
-       left.prim_index = right.prim_index = ref.prim_index;
-       left.prim_object = right.prim_object = ref.prim_object;
-       left.bounds = right.bounds = BoundBox();
-
-       /* loop over vertices/edges. */
-       Object *ob = objects[ref.prim_object];
-       const Mesh *mesh = ob->mesh;
-       const int *inds = mesh->triangles[ref.prim_index].v;
-       const float3 *verts = &mesh->verts[0];
-       const float3* v1 = &verts[inds[2]];
-
-       for(int i = 0; i < 3; i++) {
-               const float3* v0 = v1;
-               int vindex = inds[i];
-               v1 = &verts[vindex];
-               float v0p = (*v0)[dim];
-               float v1p = (*v1)[dim];
-
-               /* insert vertex to the boxes it belongs to. */
-               if(v0p <= pos)
-                       left.bounds.grow(*v0);
-
-               if(v0p >= pos)
-                       right.bounds.grow(*v0);
-
-               /* edge intersects the plane => insert intersection to both boxes. */
-               if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
-                       float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
-                       left.bounds.grow(t);
-                       right.bounds.grow(t);
-               }
-       }
+       /* perform the best found tree rotation */
+       InnerNode *child = (InnerNode*)parent->children[best_child];
 
-       /* intersect with original bounds. */
-       left.bounds.max[dim] = pos;
-       right.bounds.min[dim] = pos;
-       left.bounds.intersect(ref.bounds);
-       right.bounds.intersect(ref.bounds);
+       swap(parent->children[best_other], child->children[bets_target]);
+       child->m_bounds = merge(child->children[0]->m_bounds, child->children[1]->m_bounds);
 }
 
 CCL_NAMESPACE_END
index 1fa1951d7f20170e991ec4a24a74f60c2471bb95..84e14632b4b34ce099e499f9e7b82f496ec69e8c 100644 (file)
 #include <float.h>
 
 #include "bvh.h"
+#include "bvh_binning.h"
 
 #include "util_boundbox.h"
+#include "util_task.h"
 #include "util_vector.h"
 
 CCL_NAMESPACE_BEGIN
@@ -37,28 +39,7 @@ class Progress;
 class BVHBuild
 {
 public:
-       struct Reference
-       {
-               int prim_index;
-               int prim_object;
-               BoundBox bounds;
-
-               Reference()
-               {
-               }
-       };
-
-       struct NodeSpec
-       {
-               int num;
-               BoundBox bounds;
-
-               NodeSpec()
-               {
-                       num = 0;
-               }
-       };
-
+       /* Constructor/Destructor */
        BVHBuild(
                const vector<Object*>& objects,
                vector<int>& prim_index,
@@ -70,63 +51,37 @@ public:
        BVHNode *run();
 
 protected:
+       friend class BVHMixedSplit;
+       friend class BVHObjectSplit;
+       friend class BVHSpatialSplit;
+
        /* adding references */
-       void add_reference_mesh(NodeSpec& root, Mesh *mesh, int i);
-       void add_reference_object(NodeSpec& root, Object *ob, int i);
-       void add_references(NodeSpec& root);
+       void add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i);
+       void add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i);
+       void add_references(BVHRange& root);
 
        /* building */
-       BVHNode *build_node(const NodeSpec& spec, int level, float progress_start, float progress_end);
-       BVHNode *create_leaf_node(const NodeSpec& spec);
-       BVHNode *create_object_leaf_nodes(const Reference *ref, int num);
-
-       void progress_update(float progress_start, float progress_end);
-
-       /* object splits */
-       struct ObjectSplit
-       {
-               float sah;
-               int dim;
-               int num_left;
-               BoundBox left_bounds;
-               BoundBox right_bounds;
-
-               ObjectSplit()
-               : sah(FLT_MAX), dim(0), num_left(0)
-               {
-               }
-       };
-
-       ObjectSplit find_object_split(const NodeSpec& spec, float nodeSAH);
-       void do_object_split(NodeSpec& left, NodeSpec& right, const NodeSpec& spec, const ObjectSplit& split);
-
-       /* spatial splits */
-       struct SpatialSplit
-       {
-               float sah;
-               int dim;
-               float pos;
-
-               SpatialSplit()
-               : sah(FLT_MAX), dim(0), pos(0.0f)
-               {
-               }
-       };
-
-       struct SpatialBin
-       {
-               BoundBox bounds;
-               int enter;
-               int exit;
-       };
-
-       SpatialSplit find_spatial_split(const NodeSpec& spec, float nodeSAH);
-       void do_spatial_split(NodeSpec& left, NodeSpec& right, const NodeSpec& spec, const SpatialSplit& split);
-       void split_reference(Reference& left, Reference& right, const Reference& ref, int dim, float pos);
+       BVHNode *build_node(const BVHRange& range, int level);
+       BVHNode *build_node(const BVHObjectBinning& range, int level);
+       BVHNode *create_leaf_node(const BVHRange& range);
+       BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num);
+
+       /* threads */
+       enum { THREAD_TASK_SIZE = 4096 };
+       void thread_build_node(Task *task_, int thread_id);
+       thread_mutex build_mutex;
+
+       /* progress */
+       void progress_update();
+
+       /* tree rotations */
+       void rotate(BVHNode *node, int max_depth);
+       void rotate(BVHNode *node, int max_depth, int iterations);
 
        /* objects and primitive references */
        vector<Object*> objects;
-       vector<Reference> references;
+       vector<BVHReference> references;
+       int num_original_references;
 
        /* output primitive indexes and objects */
        vector<int>& prim_index;
@@ -138,12 +93,17 @@ protected:
        /* progress reporting */
        Progress& progress;
        double progress_start_time;
-       int progress_num_duplicates;
+       size_t progress_count;
+       size_t progress_total;
+       size_t progress_original_total;
 
        /* spatial splitting */
        float spatial_min_overlap;
        vector<BoundBox> spatial_right_bounds;
-       SpatialBin spatial_bins[3][BVHParams::NUM_SPATIAL_BINS];
+       BVHSpatialBin spatial_bins[3][BVHParams::NUM_SPATIAL_BINS];
+
+       /* threads */
+       TaskPool task_pool;
 };
 
 CCL_NAMESPACE_END
index 63683bae4a363bf533a74e55303087b2869f47bd..4edfb4b70a4a3ad11fe3aa668e2079d3f6b22b60 100644 (file)
@@ -24,6 +24,8 @@
 
 CCL_NAMESPACE_BEGIN
 
+/* BVH Node */
+
 int BVHNode::getSubtreeSize(BVH_STAT stat) const
 {
        int cnt = 0;
@@ -59,7 +61,8 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
 void BVHNode::deleteSubtree()
 {
        for(int i=0;i<num_children();i++)
-               get_child(i)->deleteSubtree();
+               if(get_child(i))
+                       get_child(i)->deleteSubtree();
 
        delete this;
 }
@@ -70,12 +73,27 @@ float BVHNode::computeSubtreeSAHCost(const BVHParams& p, float probability) cons
 
        for(int i=0;i<num_children();i++) {
                BVHNode *child = get_child(i);
-               SAH += child->computeSubtreeSAHCost(p, probability * child->m_bounds.area()/m_bounds.area());
+               SAH += child->computeSubtreeSAHCost(p, probability * child->m_bounds.safe_area()/m_bounds.safe_area());
        }
 
        return SAH;
 }
 
+uint BVHNode::update_visibility()
+{
+       if(!is_leaf() && m_visibility == 0) {
+               InnerNode *inner = (InnerNode*)this;
+               BVHNode *child0 = inner->children[0];
+               BVHNode *child1 = inner->children[1];
+
+               m_visibility = child0->update_visibility()|child1->update_visibility();
+       }
+
+       return m_visibility;
+}
+
+/* Inner Node */
+
 void InnerNode::print(int depth) const
 {
        for(int i = 0; i < depth; i++)
index 5e0a17a11936f8d0cf30b6552740d195c97eabf6..5c00f7b7a3867f8474a43669bcba202a2cb15efa 100644 (file)
@@ -49,8 +49,6 @@ public:
        virtual int num_triangles() const { return 0; }
        virtual void print(int depth = 0) const = 0;
 
-       float getArea() const { return m_bounds.area(); }
-
        BoundBox m_bounds;
        uint m_visibility;
 
@@ -58,6 +56,8 @@ public:
        int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const;
        float computeSubtreeSAHCost(const BVHParams& p, float probability = 1.0f) const;        
        void deleteSubtree();
+
+       uint update_visibility();
 };
 
 class InnerNode : public BVHNode
@@ -66,9 +66,21 @@ public:
        InnerNode(const BoundBox& bounds, BVHNode* child0, BVHNode* child1)
        {
                m_bounds = bounds;
-               m_visibility = child0->m_visibility|child1->m_visibility;
                children[0] = child0;
                children[1] = child1;
+
+               if(child0 && child1)
+                       m_visibility = child0->m_visibility|child1->m_visibility;
+               else
+                       m_visibility = 0; /* happens on build cancel */
+       }
+
+       InnerNode(const BoundBox& bounds)
+       {
+               m_bounds = bounds;
+               m_visibility = 0;
+               children[0] = NULL;
+               children[1] = NULL;
        }
 
        bool is_leaf() const { return false; }
index 38093438500bd5fbad51ef3443ebc31de0a36292..0cf5e905fea535591612a2abeaa210604ec6d6ac 100644 (file)
@@ -18,6 +18,8 @@
 #ifndef __BVH_PARAMS_H__
 #define __BVH_PARAMS_H__
 
+#include "util_boundbox.h"
+
 CCL_NAMESPACE_BEGIN
 
 /* BVH Parameters */
@@ -73,14 +75,97 @@ public:
        }
 
        /* SAH costs */
-       float cost(int num_nodes, int num_tris) const
+       __forceinline float cost(int num_nodes, int num_tris) const
        { return node_cost(num_nodes) + triangle_cost(num_tris); }
 
-       float triangle_cost(int n) const
+       __forceinline float triangle_cost(int n) const
        { return n*sah_triangle_cost; }
 
-       float node_cost(int n) const
+       __forceinline float node_cost(int n) const
        { return n*sah_node_cost; }
+
+       __forceinline bool small_enough_for_leaf(int size, int level)
+       { return (size <= min_leaf_size || level >= MAX_DEPTH); }
+};
+
+/* BVH Reference
+ *
+ * Reference to a primitive. Primitive index and object are sneakily packed
+ * into BoundBox to reduce memory usage and align nicely */
+
+class BVHReference
+{
+public:
+       __forceinline BVHReference() {}
+
+       __forceinline BVHReference(const BoundBox& bounds_, int prim_index, int prim_object)
+       : rbounds(bounds_)
+       {
+               rbounds.min.w = __int_as_float(prim_index);
+               rbounds.max.w = __int_as_float(prim_object);
+       }
+
+       __forceinline const BoundBox& bounds() const { return rbounds; }
+       __forceinline int prim_index() const { return __float_as_int(rbounds.min.w); }
+       __forceinline int prim_object() const { return __float_as_int(rbounds.max.w); }
+
+protected:
+       BoundBox rbounds;
+};
+
+/* BVH Range
+ *
+ * Build range used during construction, to indicate the bounds and place in
+ * the reference array of a subset of pirmitives Again uses trickery to pack
+ * integers into BoundBox for alignment purposes. */
+
+class BVHRange
+{
+public:
+       __forceinline BVHRange()
+       {
+               rbounds.min.w = __int_as_float(0);
+               rbounds.max.w = __int_as_float(0);
+       }
+
+       __forceinline BVHRange(const BoundBox& bounds_, int start_, int size_)
+       : rbounds(bounds_)
+       {
+               rbounds.min.w = __int_as_float(start_);
+               rbounds.max.w = __int_as_float(size_);
+       }
+
+       __forceinline BVHRange(const BoundBox& bounds_, const BoundBox& cbounds_, int start_, int size_)
+       : rbounds(bounds_), cbounds(cbounds_)
+       {
+               rbounds.min.w = __int_as_float(start_);
+               rbounds.max.w = __int_as_float(size_);
+       }
+
+       __forceinline void set_start(int start_) { rbounds.min.w = __int_as_float(start_); }
+
+       __forceinline const BoundBox& bounds() const { return rbounds; }
+       __forceinline const BoundBox& cent_bounds() const { return cbounds; }
+       __forceinline int start() const { return __float_as_int(rbounds.min.w); }
+       __forceinline int size() const { return __float_as_int(rbounds.max.w); }
+       __forceinline int end() const { return start() + size(); }
+
+protected:
+       BoundBox rbounds;
+       BoundBox cbounds;
+};
+
+/* BVH Spatial Bin */
+
+struct BVHSpatialBin
+{
+       BoundBox bounds;
+       int enter;
+       int exit;
+
+       __forceinline BVHSpatialBin()
+       {
+       }
 };
 
 CCL_NAMESPACE_END
index ee4531a4843ac5d58a29947ab0e00b3e3c6f6fa9..bef384be592b37c776ec7089dff1be9d7cd3c1a7 100644 (file)
@@ -32,23 +32,23 @@ public:
                dim = dim_;
        }
 
-       bool operator()(const BVHBuild::Reference& ra, const BVHBuild::Reference& rb)
+       bool operator()(const BVHReference& ra, const BVHReference& rb)
        {
-               float ca = ra.bounds.min[dim] + ra.bounds.max[dim];
-               float cb = rb.bounds.min[dim] + rb.bounds.max[dim];
+               float ca = ra.bounds().min[dim] + ra.bounds().max[dim];
+               float cb = rb.bounds().min[dim] + rb.bounds().max[dim];
 
                if(ca < cb) return true;
                else if(ca > cb) return false;
-               else if(ra.prim_object < rb.prim_object) return true;
-               else if(ra.prim_object > rb.prim_object) return false;
-               else if(ra.prim_index < rb.prim_index) return true;
-               else if(ra.prim_index > rb.prim_index) return false;
+               else if(ra.prim_object() < rb.prim_object()) return true;
+               else if(ra.prim_object() > rb.prim_object()) return false;
+               else if(ra.prim_index() < rb.prim_index()) return true;
+               else if(ra.prim_index() > rb.prim_index()) return false;
 
                return false;
        }
 };
 
-void bvh_reference_sort(int start, int end, BVHBuild::Reference *data, int dim)
+void bvh_reference_sort(int start, int end, BVHReference *data, int dim)
 {
        sort(data+start, data+end, BVHReferenceCompare(dim));
 }
index f06769481468f015ba796283861201eba2d9b1e4..ba35ba3fae70dbdfb388badfb61e213f6d515c19 100644 (file)
@@ -20,7 +20,7 @@
 
 CCL_NAMESPACE_BEGIN
 
-void bvh_reference_sort(int start, int end, BVHBuild::Reference *data, int dim);
+void bvh_reference_sort(int start, int end, BVHReference *data, int dim);
 
 CCL_NAMESPACE_END
 
index cceec8b8e5c73d5c7a3dc04874321c049dfd6553..42dda1180c7318642fec0eb51772079efc32f193 100644 (file)
@@ -58,15 +58,6 @@ void DeviceTask::split_max_size(list<DeviceTask>& tasks, int max_size)
        split(tasks, num);
 }
 
-void DeviceTask::split(ThreadQueue<DeviceTask>& queue, int num)
-{
-       list<DeviceTask> tasks;
-       split(tasks, num);
-
-       foreach(DeviceTask& task, tasks)
-               queue.push(task);
-}
-
 void DeviceTask::split(list<DeviceTask>& tasks, int num)
 {
        if(type == SHADER) {
index af2567498d920a072bdbc1cc45c0308bf9fb33bf..87f255e54e78399cedcc37f16774797f5b03e212 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "util_list.h"
 #include "util_string.h"
+#include "util_task.h"
 #include "util_thread.h"
 #include "util_types.h"
 #include "util_vector.h"
@@ -66,7 +67,7 @@ public:
 
 /* Device Task */
 
-class DeviceTask {
+class DeviceTask : public Task {
 public:
        typedef enum { PATH_TRACE, TONEMAP, SHADER } Type;
        Type type;
@@ -87,7 +88,6 @@ public:
        DeviceTask(Type type = PATH_TRACE);
 
        void split(list<DeviceTask>& tasks, int num);
-       void split(ThreadQueue<DeviceTask>& tasks, int num);
        void split_max_size(list<DeviceTask>& tasks, int max_size);
 };
 
index da977ed8472e6cf17368457d0c2bfc20e272e9f5..ec84047c44fe8e9fb88489de27a72f810b85cc91 100644 (file)
@@ -40,35 +40,21 @@ CCL_NAMESPACE_BEGIN
 class CPUDevice : public Device
 {
 public:
-       vector<thread*> threads;
-       ThreadQueue<DeviceTask> tasks;
+       TaskPool task_pool;
        KernelGlobals *kg;
        
        CPUDevice(int threads_num)
+       : task_pool(function_bind(&CPUDevice::thread_run, this, _1, _2))
        {
                kg = kernel_globals_create();
 
                /* do now to avoid thread issues */
                system_cpu_support_optimized();
-
-               if(threads_num == 0)
-                       threads_num = system_cpu_thread_count();
-
-               threads.resize(threads_num);
-
-               for(size_t i = 0; i < threads.size(); i++)
-                       threads[i] = new thread(function_bind(&CPUDevice::thread_run, this, i));
        }
 
        ~CPUDevice()
        {
-               tasks.stop();
-
-               foreach(thread *t, threads) {
-                       t->join();
-                       delete t;
-               }
-
+               task_pool.stop();
                kernel_globals_free(kg);
        }
 
@@ -127,25 +113,21 @@ public:
 #endif
        }
 
-       void thread_run(int t)
+       void thread_run(Task *task_, int thread_id)
        {
-               DeviceTask task;
-
-               while(tasks.worker_wait_pop(task)) {
-                       if(task.type == DeviceTask::PATH_TRACE)
-                               thread_path_trace(task);
-                       else if(task.type == DeviceTask::TONEMAP)
-                               thread_tonemap(task);
-                       else if(task.type == DeviceTask::SHADER)
-                               thread_shader(task);
-
-                       tasks.worker_done();
-               }
+               DeviceTask *task = (DeviceTask*)task_;
+
+               if(task->type == DeviceTask::PATH_TRACE)
+                       thread_path_trace(*task);
+               else if(task->type == DeviceTask::TONEMAP)
+                       thread_tonemap(*task);
+               else if(task->type == DeviceTask::SHADER)
+                       thread_shader(*task);
        }
 
        void thread_path_trace(DeviceTask& task)
        {
-               if(tasks.worker_cancel())
+               if(task_pool.cancelled())
                        return;
 
 #ifdef WITH_OSL
@@ -160,7 +142,7 @@ public:
                                        kernel_cpu_optimized_path_trace(kg, (float*)task.buffer, (unsigned int*)task.rng_state,
                                                task.sample, x, y, task.offset, task.stride);
 
-                               if(tasks.worker_cancel())
+                               if(task_pool.cancelled())
                                        break;
                        }
                }
@@ -172,7 +154,7 @@ public:
                                        kernel_cpu_path_trace(kg, (float*)task.buffer, (unsigned int*)task.rng_state,
                                                task.sample, x, y, task.offset, task.stride);
 
-                               if(tasks.worker_cancel())
+                               if(task_pool.cancelled())
                                        break;
                        }
                }
@@ -214,7 +196,7 @@ public:
                        for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
                                kernel_cpu_optimized_shader(kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
 
-                               if(tasks.worker_cancel())
+                               if(task_pool.cancelled())
                                        break;
                        }
                }
@@ -224,7 +206,7 @@ public:
                        for(int x = task.shader_x; x < task.shader_x + task.shader_w; x++) {
                                kernel_cpu_shader(kg, (uint4*)task.shader_input, (float4*)task.shader_output, task.shader_eval_type, x);
 
-                               if(tasks.worker_cancel())
+                               if(task_pool.cancelled())
                                        break;
                        }
                }
@@ -239,17 +221,22 @@ public:
        {
                /* split task into smaller ones, more than number of threads for uneven
                   workloads where some parts of the image render slower than others */
-               task.split(tasks, threads.size()*10);
+               list<DeviceTask> tasks;
+
+               task.split(tasks, TaskScheduler::num_threads()*10);
+
+               foreach(DeviceTask& task, tasks)
+                       task_pool.push(new DeviceTask(task));
        }
 
        void task_wait()
        {
-               tasks.wait_done();
+               task_pool.wait();
        }
 
        void task_cancel()
        {
-               tasks.cancel();
+               task_pool.cancel();
        }
 };
 
index 1f69f2c53fa8dd6b31f629902563b8e53c09ba63..9f7d65e640b5a4a4013cd7fca6f5df4f922c8a51 100644 (file)
@@ -257,13 +257,14 @@ public:
 
        void task_add(DeviceTask& task)
        {
-               ThreadQueue<DeviceTask> tasks;
+               list<DeviceTask> tasks;
                task.split(tasks, devices.size());
 
                foreach(SubDevice& sub, devices) {
-                       DeviceTask subtask;
+                       if(!tasks.empty()) {
+                               DeviceTask subtask = tasks.front();
+                               tasks.pop_front();
 
-                       if(tasks.worker_wait_pop(subtask)) {
                                if(task.buffer) subtask.buffer = sub.ptr_map[task.buffer];
                                if(task.rng_state) subtask.rng_state = sub.ptr_map[task.rng_state];
                                if(task.rgba) subtask.rgba = sub.ptr_map[task.rgba];
index 9a52531eec006f214c61081831566c1c8a11f20b..6c3ade1c531b9f13296ed9d22954ce0e45ba5a66 100644 (file)
@@ -266,7 +266,7 @@ __device_inline void path_radiance_accum_background(PathRadiance *L, float3 thro
 #endif
 }
 
-__device_inline float3 path_radiance_sum(PathRadiance *L)
+__device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L)
 {
 #ifdef __PASSES__
        if(L->use_light_pass) {
@@ -283,9 +283,14 @@ __device_inline float3 path_radiance_sum(PathRadiance *L)
                L->indirect_glossy *= L->indirect;
                L->indirect_transmission *= L->indirect;
 
-               return L->emission + L->background
+               float3 L_sum = L->emission
                        + L->direct_diffuse + L->direct_glossy + L->direct_transmission
                        + L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission;
+
+               if(!kernel_data.background.transparent)
+                       L_sum += L->background;
+
+               return L_sum;
        }
        else
                return L->emission;
index ff12e85375ca6f447210dc20a21c5ad290930833..8ebac1772770b0e46521534d241f3ec9d558e873 100644 (file)
@@ -223,6 +223,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
 
        path_radiance_init(&L, kernel_data.film.use_light_pass);
 
+       float min_ray_pdf = FLT_MAX;
        float ray_pdf = 0.0f;
        PathState state;
        int rng_offset = PRNG_BASE_NUM;
@@ -239,13 +240,17 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
                        /* eval background shader if nothing hit */
                        if(kernel_data.background.transparent && (state.flag & PATH_RAY_CAMERA)) {
                                L_transparent += average(throughput);
+
+#ifdef __PASSES__
+                               if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
+#endif
+                                       break;
                        }
+
 #ifdef __BACKGROUND__
-                       else {
-                               /* sample background shader */
-                               float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf);
-                               path_radiance_accum_background(&L, throughput, L_background, state.bounce);
-                       }
+                       /* sample background shader */
+                       float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf);
+                       path_radiance_accum_background(&L, throughput, L_background, state.bounce);
 #endif
 
                        break;
@@ -259,6 +264,18 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
 
                kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput);
 
+               /* blurring of bsdf after bounces, for rays that have a small likelihood
+                  of following this particular path (diffuse, rough glossy) */
+               if(kernel_data.integrator.filter_glossy != FLT_MAX) {
+                       float blur_pdf = kernel_data.integrator.filter_glossy*min_ray_pdf;
+
+                       if(blur_pdf < 1.0f) {
+                               float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f;
+                               shader_bsdf_blur(kg, &sd, blur_roughness);
+                       }
+               }
+
+               /* holdout */
 #ifdef __HOLDOUT__
                if((sd.flag & SD_HOLDOUT) && (state.flag & PATH_RAY_CAMERA)) {
                        float3 holdout_weight = shader_holdout_eval(kg, &sd);
@@ -378,8 +395,10 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
                path_radiance_bsdf_bounce(&L, &throughput, &bsdf_eval, bsdf_pdf, state.bounce, label);
 
                /* set labels */
-               if(!(label & LABEL_TRANSPARENT))
+               if(!(label & LABEL_TRANSPARENT)) {
                        ray_pdf = bsdf_pdf;
+                       min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
+               }
 
                /* update path state */
                path_state_next(kg, &state, label);
@@ -394,7 +413,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
 #endif
        }
 
-       float3 L_sum = path_radiance_sum(&L);
+       float3 L_sum = path_radiance_sum(kg, &L);
 
 #ifdef __CLAMP_SAMPLE__
        path_radiance_clamp(&L, &L_sum, kernel_data.integrator.sample_clamp);
index 391dcd12dade928ce22465c96161fe8475743549..102a2bb036dc27405cbf206889a4c59953aa8d5d 100644 (file)
@@ -516,6 +516,7 @@ typedef struct KernelIntegrator {
 
        /* caustics */
        int no_caustics;
+       float filter_glossy;
 
        /* seed */
        int seed;
@@ -525,9 +526,6 @@ typedef struct KernelIntegrator {
 
        /* clamp */
        float sample_clamp;
-
-       /* padding */
-       int pad;
 } KernelIntegrator;
 
 typedef struct KernelBVH {
index f494b6d66e1c9b6c6e70b2b057b651c00432fa7d..98f8734aed29437dc05f49e990daa0f97f032407 100644 (file)
@@ -40,6 +40,15 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack
                                data = sd->P;
                        break;
                }
+               case NODE_TEXCO_NORMAL: {
+                       if(sd->object != ~0) {
+                               Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+                               data = transform_direction(&tfm, sd->N);
+                       }
+                       else
+                               data = sd->N;
+                       break;
+               }
                case NODE_TEXCO_CAMERA: {
                        Transform tfm = kernel_data.cam.worldtocamera;
 
@@ -85,6 +94,15 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa
                                data = sd->P + sd->dP.dx;
                        break;
                }
+               case NODE_TEXCO_NORMAL: {
+                       if(sd->object != ~0) {
+                               Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+                               data = transform_direction(&tfm, sd->N);
+                       }
+                       else
+                               data = sd->N;
+                       break;
+               }
                case NODE_TEXCO_CAMERA: {
                        Transform tfm = kernel_data.cam.worldtocamera;
 
@@ -133,6 +151,15 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa
                                data = sd->P + sd->dP.dy;
                        break;
                }
+               case NODE_TEXCO_NORMAL: {
+                       if(sd->object != ~0) {
+                               Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
+                               data = normalize(transform_direction(&tfm, sd->N));
+                       }
+                       else
+                               data = sd->N;
+                       break;
+               }
                case NODE_TEXCO_CAMERA: {
                        Transform tfm = kernel_data.cam.worldtocamera;
 
index 68eb39bdd29fc38e7d6fcc6706b4cf06873ee834..fa7c211b5f9f0865685e0308cef93d591acae49a 100644 (file)
@@ -119,6 +119,7 @@ typedef enum NodeLightPath {
 } NodeLightPath;
 
 typedef enum NodeTexCoord {
+       NODE_TEXCO_NORMAL,
        NODE_TEXCO_OBJECT,
        NODE_TEXCO_CAMERA,
        NODE_TEXCO_WINDOW,
index 6e6d30f387925be2b141aa17c32b0c55737d4854..c1f066df10cea011e25c082381a55219ba940b91 100644 (file)
@@ -41,6 +41,7 @@ Integrator::Integrator()
        transparent_shadows = false;
 
        no_caustics = false;
+       filter_glossy = 0.0f;
        seed = 0;
        layer_flag = ~0;
        sample_clamp = 0.0f;
@@ -81,6 +82,8 @@ void Integrator::device_update(Device *device, DeviceScene *dscene)
        kintegrator->transparent_shadows = transparent_shadows;
 
        kintegrator->no_caustics = no_caustics;
+       kintegrator->filter_glossy = (filter_glossy == 0.0f)? FLT_MAX: 1.0f/filter_glossy;
+
        kintegrator->seed = hash_int(seed);
        kintegrator->layer_flag = layer_flag << PATH_RAY_LAYER_SHIFT;
 
@@ -119,6 +122,7 @@ bool Integrator::modified(const Integrator& integrator)
                transparent_probalistic == integrator.transparent_probalistic &&
                transparent_shadows == integrator.transparent_shadows &&
                no_caustics == integrator.no_caustics &&
+               filter_glossy == integrator.filter_glossy &&
                layer_flag == integrator.layer_flag &&
                seed == integrator.seed &&
                sample_clamp == integrator.sample_clamp);
index abbbaca894c1c80d9c487e4489de41360fd926a1..0817fcaa457ec807481761e15a7cab291fcddf41 100644 (file)
@@ -41,6 +41,7 @@ public:
        bool transparent_shadows;
 
        bool no_caustics;
+       float filter_glossy;
 
        int seed;
        int layer_flag;
index a7eb365f983015360ecf12ddf2deab36204317aa..0ce16e65621e82aef13f21264f3535d52555977f 100644 (file)
@@ -43,6 +43,7 @@ Mesh::Mesh()
        transform_applied = false;
        transform_negative_scaled = false;
        displacement_method = DISPLACE_BUMP;
+       bounds = BoundBox::empty;
 
        bvh = NULL;
 
@@ -96,7 +97,7 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
 
 void Mesh::compute_bounds()
 {
-       BoundBox bnds;
+       BoundBox bnds = BoundBox::empty;
        size_t verts_size = verts.size();
 
        for(size_t i = 0; i < verts_size; i++)
@@ -697,6 +698,8 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
                                progress.set_status(msg, "Building BVH");
 
                                mesh->compute_bvh(&scene->params, progress);
+
+                               i++;
                        }
 
                        if(progress.get_cancel()) return;
@@ -704,8 +707,6 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
                        mesh->need_update = false;
                        mesh->need_update_rebuild = false;
                }
-
-               i++;
        }
        
        foreach(Shader *shader, scene->shaders)
index db696993737f989a4baca11ef6a260c4f0da9286..d71438ebae1bd8053878b64d113598437ae43200 100644 (file)
@@ -1503,6 +1503,7 @@ TextureCoordinateNode::TextureCoordinateNode()
 {
        add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
        add_output("Generated", SHADER_SOCKET_POINT);
+       add_output("Normal", SHADER_SOCKET_NORMAL);
        add_output("UV", SHADER_SOCKET_POINT);
        add_output("Object", SHADER_SOCKET_POINT);
        add_output("Camera", SHADER_SOCKET_POINT);
@@ -1551,6 +1552,12 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler)
                }
        }
 
+       out = output("Normal");
+       if(!out->links.empty()) {
+               compiler.stack_assign(out);
+               compiler.add_node(texco_node, NODE_TEXCO_NORMAL, out->stack_offset);
+       }
+
        out = output("UV");
        if(!out->links.empty()) {
                int attr = compiler.attribute(Attribute::STD_UV);
index 5f7a5810c0982227c0db590e7c9a2a10e169e97b..28645d856a83a0eeaaa079950fae2334d8fd140a 100644 (file)
@@ -37,6 +37,7 @@ Object::Object()
        tfm = transform_identity();
        visibility = ~0;
        pass_id = 0;
+       bounds = BoundBox::empty;
 }
 
 Object::~Object()
index 676f42be79083bacda62bc692ea2d5d774a656a3..34a0c0ff877771fd04e30783aa75fce6061277b2 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "util_foreach.h"
 #include "util_function.h"
+#include "util_task.h"
 #include "util_time.h"
 
 CCL_NAMESPACE_BEGIN
@@ -37,6 +38,8 @@ Session::Session(const SessionParams& params_)
 {
        device_use_gl = ((params.device.type != DEVICE_CPU) && !params.background);
 
+       TaskScheduler::init(params.threads);
+
        device = Device::create(params.device, params.background, params.threads);
        buffers = new RenderBuffers(device);
        display = new DisplayBuffer(device);
@@ -88,6 +91,8 @@ Session::~Session()
        delete display;
        delete scene;
        delete device;
+
+       TaskScheduler::exit();
 }
 
 void Session::start()
index ff477296c7e14cf53df1fa9bbd86e071ac2716fe..f6acc3589596355c230b189db77e4e7624b73a38 100644 (file)
@@ -93,7 +93,7 @@ void LinearQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float
 
 BoundBox LinearQuadPatch::bound()
 {
-       BoundBox bbox;
+       BoundBox bbox = BoundBox::empty;
 
        for(int i = 0; i < 4; i++)
                bbox.grow(hull[i]);
@@ -115,7 +115,7 @@ void LinearTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, f
 
 BoundBox LinearTrianglePatch::bound()
 {
-       BoundBox bbox;
+       BoundBox bbox = BoundBox::empty;
 
        for(int i = 0; i < 3; i++)
                bbox.grow(hull[i]);
@@ -132,7 +132,7 @@ void BicubicPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, float v)
 
 BoundBox BicubicPatch::bound()
 {
-       BoundBox bbox;
+       BoundBox bbox = BoundBox::empty;
 
        for(int i = 0; i < 16; i++)
                bbox.grow(hull[i]);
@@ -152,7 +152,7 @@ void BicubicTangentPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, f
 
 BoundBox BicubicTangentPatch::bound()
 {
-       BoundBox bbox;
+       BoundBox bbox = BoundBox::empty;
 
        for(int i = 0; i < 16; i++)
                bbox.grow(hull[i]);
@@ -205,7 +205,7 @@ void GregoryQuadPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u, floa
 
 BoundBox GregoryQuadPatch::bound()
 {
-       BoundBox bbox;
+       BoundBox bbox = BoundBox::empty;
 
        for(int i = 0; i < 20; i++)
                bbox.grow(hull[i]);
@@ -276,7 +276,7 @@ void GregoryTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float u,
 
 BoundBox GregoryTrianglePatch::bound()
 {
-       BoundBox bbox;
+       BoundBox bbox = BoundBox::empty;
 
        for(int i = 0; i < 20; i++)
                bbox.grow(hull[i]);
index 9182ee4cbe1aa0e44bf5d074f0568f0babb30491..87bd84b4e0feeccef79c9e644f00f551f0cafaa2 100644 (file)
@@ -15,6 +15,7 @@ set(SRC
        util_path.cpp
        util_string.cpp
        util_system.cpp
+       util_task.cpp
        util_time.cpp
        util_transform.cpp
 )
@@ -50,6 +51,7 @@ set(SRC_HEADERS
        util_set.h
        util_string.h
        util_system.h
+       util_task.h
        util_thread.h
        util_time.h
        util_transform.h
index bb1df0b220f974a43b5d69ea663f8f3c1fbfa5a2..9511b48e1034207679341493bf94e276d109729b 100644 (file)
@@ -23,6 +23,7 @@
 #include <float.h>
 
 #include "util_math.h"
+#include "util_string.h"
 #include "util_transform.h"
 #include "util_types.h"
 
@@ -35,45 +36,81 @@ class BoundBox
 public:
        float3 min, max;
 
-       BoundBox(void)
+       __forceinline BoundBox()
        {
-               min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX);
-               max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
        }
 
-       BoundBox(const float3& min_, const float3& max_)
+       __forceinline BoundBox(const float3& pt)
+       : min(pt), max(pt)
+       {
+       }
+
+       __forceinline BoundBox(const float3& min_, const float3& max_)
        : min(min_), max(max_)
        {
        }
 
-       void grow(const float3& pt)  
+       static struct empty_t {} empty;
+
+       __forceinline BoundBox(empty_t)
+       : min(make_float3(FLT_MAX, FLT_MAX, FLT_MAX)), max(make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX))
+       {
+       }
+
+       __forceinline void grow(const float3& pt)  
        {
                min = ccl::min(min, pt);
                max = ccl::max(max, pt);
        }
 
-       void grow(const BoundBox& bbox)
+       __forceinline void grow(const BoundBox& bbox)
        {
                grow(bbox.min);
                grow(bbox.max);
        }
 
-       void intersect(const BoundBox& bbox) 
+       __forceinline void intersect(const BoundBox& bbox) 
        {
                min = ccl::max(min, bbox.min);
                max = ccl::min(max, bbox.max);
        }
 
-       float area(void) const
+       /* todo: avoid using this */
+       __forceinline float safe_area() const
        {
-               if(!valid())
+               if(!((min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z)))
                        return 0.0f;
 
+               return area();
+       }
+
+       __forceinline float area() const
+       {
+               return half_area()*2.0f;
+       }
+
+       __forceinline float half_area() const
+       {
                float3 d = max - min;
-               return dot(d, d)*2.0f;
+               return (d.x*d.z + d.y*d.z + d.x*d.y);
+       }
+
+       __forceinline float3 center() const
+       {
+               return 0.5f*(min + max);
        }
 
-       bool valid(void) const
+       __forceinline float3 center2() const
+       {
+               return min + max;
+       }
+
+       __forceinline float3 size() const
+       {
+               return max - min;
+       }
+       
+       __forceinline bool valid() const
        {
                return (min.x <= max.x) && (min.y <= max.y) && (min.z <= max.z) &&
                       (isfinite(min.x) && isfinite(min.y) && isfinite(min.z)) &&
@@ -82,7 +119,7 @@ public:
 
        BoundBox transformed(const Transform *tfm)
        {
-               BoundBox result;
+               BoundBox result = BoundBox::empty;
 
                for(int i = 0; i < 8; i++) {
                        float3 p;
@@ -98,6 +135,31 @@ public:
        }
 };
 
+__forceinline BoundBox merge(const BoundBox& bbox, const float3& pt)
+{
+       return BoundBox(min(bbox.min, pt), max(bbox.max, pt));
+}
+
+__forceinline BoundBox merge(const BoundBox& a, const BoundBox& b)
+{
+       return BoundBox(min(a.min, b.min), max(a.max, b.max));
+}
+
+__forceinline BoundBox merge(const BoundBox& a, const BoundBox& b, const BoundBox& c, const BoundBox& d)
+{
+       return merge(merge(a, b), merge(c, d));
+}
+
+__forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b)
+{
+       return BoundBox(max(a.min, b.min), min(a.max, b.max));
+}
+
+__forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b, const BoundBox& c)
+{
+       return intersect(a, intersect(b, c));
+}
+
 CCL_NAMESPACE_END
 
 #endif /* __UTIL_BOUNDBOX_H__ */
index 019dede07fab0e87435449710e7e719cddf5549b..53c1302b4a1168df554279c9f23eb64f41b81349 100644 (file)
@@ -182,93 +182,74 @@ __device_inline float average(const float2 a)
 
 __device_inline float2 operator-(const float2 a)
 {
-       float2 r = {-a.x, -a.y};
-       return r;
+       return make_float2(-a.x, -a.y);
 }
 
 __device_inline float2 operator*(const float2 a, const float2 b)
 {
-       float2 r = {a.x*b.x, a.y*b.y};
-       return r;
+       return make_float2(a.x*b.x, a.y*b.y);
 }
 
 __device_inline float2 operator*(const float2 a, float f)
 {
-       float2 r = {a.x*f, a.y*f};
-       return r;
+       return make_float2(a.x*f, a.y*f);
 }
 
 __device_inline float2 operator*(float f, const float2 a)
 {
-       float2 r = {a.x*f, a.y*f};
-       return r;
+       return make_float2(a.x*f, a.y*f);
 }
 
 __device_inline float2 operator/(float f, const float2 a)
 {
-       float2 r = {f/a.x, f/a.y};
-       return r;
+       return make_float2(f/a.x, f/a.y);
 }
 
 __device_inline float2 operator/(const float2 a, float f)
 {
        float invf = 1.0f/f;
-       float2 r = {a.x*invf, a.y*invf};
-       return r;
+       return make_float2(a.x*invf, a.y*invf);
 }
 
 __device_inline float2 operator/(const float2 a, const float2 b)
 {
-       float2 r = {a.x/b.x, a.y/b.y};
-       return r;
+       return make_float2(a.x/b.x, a.y/b.y);
 }
 
 __device_inline float2 operator+(const float2 a, const float2 b)
 {
-       float2 r = {a.x+b.x, a.y+b.y};
-       return r;
+       return make_float2(a.x+b.x, a.y+b.y);
 }
 
 __device_inline float2 operator-(const float2 a, const float2 b)
 {
-       float2 r = {a.x-b.x, a.y-b.y};
-       return r;
+       return make_float2(a.x-b.x, a.y-b.y);
 }
 
 __device_inline float2 operator+=(float2& a, const float2 b)
 {
-       a.x += b.x;
-       a.y += b.y;
-       return a;
+       return a = a + b;
 }
 
 __device_inline float2 operator*=(float2& a, const float2 b)
 {
-       a.x *= b.x;
-       a.y *= b.y;
-       return a;
+       return a = a * b;
 }
 
 __device_inline float2 operator*=(float2& a, float f)
 {
-       a.x *= f;
-       a.y *= f;
-       return a;
+       return a = a * f;
 }
 
 __device_inline float2 operator/=(float2& a, const float2 b)
 {
-       a.x /= b.x;
-       a.y /= b.y;
-       return a;
+       return a = a / b;
 }
 
 __device_inline float2 operator/=(float2& a, float f)
 {
        float invf = 1.0f/f;
-       a.x *= invf;
-       a.y *= invf;
-       return a;
+       return a = a * invf;
 }
 
 
@@ -314,14 +295,12 @@ __device_inline bool operator!=(const float2 a, const float2 b)
 
 __device_inline float2 min(float2 a, float2 b)
 {
-       float2 r = {min(a.x, b.x), min(a.y, b.y)};
-       return r;
+       return make_float2(min(a.x, b.x), min(a.y, b.y));
 }
 
 __device_inline float2 max(float2 a, float2 b)
 {
-       float2 r = {max(a.x, b.x), max(a.y, b.y)};
-       return r;
+       return make_float2(max(a.x, b.x), max(a.y, b.y));
 }
 
 __device_inline float2 clamp(float2 a, float2 mn, float2 mx)
@@ -361,112 +340,78 @@ __device_inline float2 interp(float2 a, float2 b, float t)
 
 /* Float3 Vector */
 
-__device_inline bool is_zero(const float3 a)
-{
-       return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f);
-}
-
-__device_inline float average(const float3 a)
-{
-       return (a.x + a.y + a.z)*(1.0f/3.0f);
-}
-
 #ifndef __KERNEL_OPENCL__
 
 __device_inline float3 operator-(const float3 a)
 {
-       float3 r = make_float3(-a.x, -a.y, -a.z);
-       return r;
+       return make_float3(-a.x, -a.y, -a.z);
 }
 
 __device_inline float3 operator*(const float3 a, const float3 b)
 {
-       float3 r = make_float3(a.x*b.x, a.y*b.y, a.z*b.z);
-       return r;
+       return make_float3(a.x*b.x, a.y*b.y, a.z*b.z);
 }
 
 __device_inline float3 operator*(const float3 a, float f)
 {
-       float3 r = make_float3(a.x*f, a.y*f, a.z*f);
-       return r;
+       return make_float3(a.x*f, a.y*f, a.z*f);
 }
 
 __device_inline float3 operator*(float f, const float3 a)
 {
-       float3 r = make_float3(a.x*f, a.y*f, a.z*f);
-       return r;
+       return make_float3(a.x*f, a.y*f, a.z*f);
 }
 
 __device_inline float3 operator/(float f, const float3 a)
 {
-       float3 r = make_float3(f/a.x, f/a.y, f/a.z);
-       return r;
+       return make_float3(f/a.x, f/a.y, f/a.z);
 }
 
 __device_inline float3 operator/(const float3 a, float f)
 {
        float invf = 1.0f/f;
-       float3 r = make_float3(a.x*invf, a.y*invf, a.z*invf);
-       return r;
+       return make_float3(a.x*invf, a.y*invf, a.z*invf);
 }
 
 __device_inline float3 operator/(const float3 a, const float3 b)
 {
-       float3 r = make_float3(a.x/b.x, a.y/b.y, a.z/b.z);
-       return r;
+       return make_float3(a.x/b.x, a.y/b.y, a.z/b.z);
 }
 
 __device_inline float3 operator+(const float3 a, const float3 b)
 {
-       float3 r = make_float3(a.x+b.x, a.y+b.y, a.z+b.z);
-       return r;
+       return make_float3(a.x+b.x, a.y+b.y, a.z+b.z);
 }
 
 __device_inline float3 operator-(const float3 a, const float3 b)
 {
-       float3 r = make_float3(a.x-b.x, a.y-b.y, a.z-b.z);
-       return r;
+       return make_float3(a.x-b.x, a.y-b.y, a.z-b.z);
 }
 
 __device_inline float3 operator+=(float3& a, const float3 b)
 {
-       a.x += b.x;
-       a.y += b.y;
-       a.z += b.z;
-       return a;
+       return a = a + b;
 }
 
 __device_inline float3 operator*=(float3& a, const float3 b)
 {
-       a.x *= b.x;
-       a.y *= b.y;
-       a.z *= b.z;
-       return a;
+       return a = a * b;
 }
 
 __device_inline float3 operator*=(float3& a, float f)
 {
-       a.x *= f;
-       a.y *= f;
-       a.z *= f;
-       return a;
+       return a = a * f;
 }
 
 __device_inline float3 operator/=(float3& a, const float3 b)
 {
-       a.x /= b.x;
-       a.y /= b.y;
-       a.z /= b.z;
-       return a;
+       return a = a / b;
 }
 
 __device_inline float3 operator/=(float3& a, float f)
 {
        float invf = 1.0f/f;
-       a.x *= invf;
-       a.y *= invf;
-       a.z *= invf;
-       return a;
+       return a = a * invf;
 }
 
 __device_inline float dot(const float3 a, const float3 b)
@@ -506,7 +451,11 @@ __device_inline float3 normalize_len(const float3 a, float *t)
 
 __device_inline bool operator==(const float3 a, const float3 b)
 {
+#ifdef __KERNEL_SSE__
+       return (_mm_movemask_ps(_mm_cmpeq_ps(a.m128, b.m128)) & 7) == 7;
+#else
        return (a.x == b.x && a.y == b.y && a.z == b.z);
+#endif
 }
 
 __device_inline bool operator!=(const float3 a, const float3 b)
@@ -516,14 +465,20 @@ __device_inline bool operator!=(const float3 a, const float3 b)
 
 __device_inline float3 min(float3 a, float3 b)
 {
-       float3 r = make_float3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
-       return r;
+#ifdef __KERNEL_SSE__
+       return _mm_min_ps(a.m128, b.m128);
+#else
+       return make_float3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
+#endif
 }
 
 __device_inline float3 max(float3 a, float3 b)
 {
-       float3 r = make_float3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
-       return r;
+#ifdef __KERNEL_SSE__
+       return _mm_max_ps(a.m128, b.m128);
+#else
+       return make_float3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
+#endif
 }
 
 __device_inline float3 clamp(float3 a, float3 mn, float3 mx)
@@ -533,7 +488,12 @@ __device_inline float3 clamp(float3 a, float3 mn, float3 mx)
 
 __device_inline float3 fabs(float3 a)
 {
+#ifdef __KERNEL_SSE__
+       __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x7fffffff));
+       return _mm_and_ps(a.m128, mask);
+#else
        return make_float3(fabsf(a.x), fabsf(a.y), fabsf(a.z));
+#endif
 }
 
 #endif
@@ -555,6 +515,16 @@ __device_inline void print_float3(const char *label, const float3& a)
        printf("%s: %.8f %.8f %.8f\n", label, a.x, a.y, a.z);
 }
 
+__device_inline float3 rcp(const float3& a)
+{
+#ifdef __KERNEL_SSE__
+       float4 r = _mm_rcp_ps(a.m128);
+       return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+#else
+       return make_float3(1.0f/a.x, 1.0f/a.y, 1.0f/a.z);
+#endif
+}
+
 #endif
 
 __device_inline float3 interp(float3 a, float3 b, float t)
@@ -562,122 +532,257 @@ __device_inline float3 interp(float3 a, float3 b, float t)
        return a + t*(b - a);
 }
 
+__device_inline bool is_zero(const float3 a)
+{
+#ifdef __KERNEL_SSE__
+       return a == make_float3(0.0f);
+#else
+       return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f);
+#endif
+}
+
+__device_inline float reduce_add(const float3 a)
+{
+#ifdef __KERNEL_SSE__
+       return (a.x + a.y + a.z);
+#else
+       return (a.x + a.y + a.z);
+#endif
+}
+
+__device_inline float average(const float3 a)
+{
+       return reduce_add(a)*(1.0f/3.0f);
+}
+
 /* Float4 Vector */
 
-#ifndef __KERNEL_OPENCL__
+#ifdef __KERNEL_SSE__
 
-__device_inline bool is_zero(const float4& a)
+template<size_t index_0, size_t index_1, size_t index_2, size_t index_3> __forceinline const float4 shuffle(const float4& b)
 {
-       return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f && a.w == 0.0f);
+       return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(index_3, index_2, index_1, index_0)));
 }
 
-__device_inline float average(const float4& a)
+template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4& b)
 {
-       return (a.x + a.y + a.z + a.w)*(1.0f/4.0f);
+       return _mm_moveldup_ps(b);
 }
 
+template<> __forceinline const float4 shuffle<1, 1, 3, 3>(const float4& b)
+{
+       return _mm_movehdup_ps(b);
+}
+
+template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& b)
+{
+       return _mm_castpd_ps(_mm_movedup_pd(_mm_castps_pd(b)));
+}
+
+#endif
+
+#ifndef __KERNEL_OPENCL__
+
 __device_inline float4 operator-(const float4& a)
 {
-       float4 r = {-a.x, -a.y, -a.z, -a.w};
-       return r;
+#ifdef __KERNEL_SSE__
+       __m128 mask = _mm_castsi128_ps(_mm_set1_epi32(0x80000000));
+       return _mm_xor_ps(a.m128, mask);
+#else
+       return make_float4(-a.x, -a.y, -a.z, -a.w);
+#endif
 }
 
 __device_inline float4 operator*(const float4& a, const float4& b)
 {
-       float4 r = {a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w};
-       return r;
+#ifdef __KERNEL_SSE__
+       return _mm_mul_ps(a.m128, b.m128);
+#else
+       return make_float4(a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w);
+#endif
 }
 
 __device_inline float4 operator*(const float4& a, float f)
 {
-       float4 r = {a.x*f, a.y*f, a.z*f, a.w*f};
-       return r;
+#ifdef __KERNEL_SSE__
+       return a * make_float4(f);
+#else
+       return make_float4(a.x*f, a.y*f, a.z*f, a.w*f);
+#endif
 }
 
 __device_inline float4 operator*(float f, const float4& a)
 {
-       float4 r = {a.x*f, a.y*f, a.z*f, a.w*f};
-       return r;
+       return a * f;
+}
+
+__device_inline float4 rcp(const float4& a)
+{
+#ifdef __KERNEL_SSE__
+       float4 r = _mm_rcp_ps(a.m128);
+       return _mm_sub_ps(_mm_add_ps(r, r), _mm_mul_ps(_mm_mul_ps(r, r), a));
+#else
+       return make_float4(1.0f/a.x, 1.0f/a.y, 1.0f/a.z, 1.0f/a.w);
+#endif
 }
 
 __device_inline float4 operator/(const float4& a, float f)
 {
-       float invf = 1.0f/f;
-       float4 r = {a.x*invf, a.y*invf, a.z*invf, a.w*invf};
-       return r;
+       return a * (1.0f/f);
 }
 
 __device_inline float4 operator/(const float4& a, const float4& b)
 {
-       float4 r = {a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w};
-       return r;
+#ifdef __KERNEL_SSE__
+       return a * rcp(b);
+#else
+       return make_float4(a.x/b.x, a.y/b.y, a.z/b.z, a.w/b.w);
+#endif
+
 }
 
 __device_inline float4 operator+(const float4& a, const float4& b)
 {
-       float4 r = {a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w};
-       return r;
+#ifdef __KERNEL_SSE__
+       return _mm_add_ps(a.m128, b.m128);
+#else
+       return make_float4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
+#endif
 }
 
 __device_inline float4 operator-(const float4& a, const float4& b)
 {
-       float4 r = {a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w};
-       return r;
+#ifdef __KERNEL_SSE__
+       return _mm_sub_ps(a.m128, b.m128);
+#else
+       return make_float4(a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w);
+#endif
 }
 
 __device_inline float4 operator+=(float4& a, const float4& b)
 {
-       a.x += b.x;
-       a.y += b.y;
-       a.z += b.z;
-       a.w += b.w;
-       return a;
+       return a = a + b;
 }
 
 __device_inline float4 operator*=(float4& a, const float4& b)
 {
-       a.x *= b.x;
-       a.y *= b.y;
-       a.z *= b.z;
-       a.w *= b.w;
-       return a;
+       return a = a * b;
 }
 
 __device_inline float4 operator/=(float4& a, float f)
 {
-       float invf = 1.0f/f;
-       a.x *= invf;
-       a.y *= invf;
-       a.z *= invf;
-       a.w *= invf;
-       return a;
+       return a = a / f;
 }
 
-__device_inline float dot(const float4& a, const float4& b)
+__device_inline int4 operator<(const float4& a, const float4& b)
 {
-       return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
+#ifdef __KERNEL_SSE__
+       return _mm_cvtps_epi32(_mm_cmplt_ps(a.m128, b.m128)); /* todo: avoid cvt */
+#else
+       return make_int4(a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w);
+#endif
+}
+
+__device_inline int4 operator>=(float4 a, float4 b)
+{
+#ifdef __KERNEL_SSE__
+       return _mm_cvtps_epi32(_mm_cmpge_ps(a.m128, b.m128)); /* todo: avoid cvt */
+#else
+       return make_int4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w);
+#endif
+}
+
+__device_inline int4 operator<=(const float4& a, const float4& b)
+{
+#ifdef __KERNEL_SSE__
+       return _mm_cvtps_epi32(_mm_cmple_ps(a.m128, b.m128)); /* todo: avoid cvt */
+#else
+       return make_int4(a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w);
+#endif
+}
+
+__device_inline bool operator==(const float4 a, const float4 b)
+{
+#ifdef __KERNEL_SSE__
+       return (_mm_movemask_ps(_mm_cmpeq_ps(a.m128, b.m128)) & 15) == 15;
+#else
+       return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
+#endif
 }
 
 __device_inline float4 cross(const float4& a, const float4& b)
 {
-       float4 r = {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x, 0.0f};
-       return r;
+#ifdef __KERNEL_SSE__
+       return (shuffle<1,2,0,0>(a)*shuffle<2,0,1,0>(b)) - (shuffle<2,0,1,0>(a)*shuffle<1,2,0,0>(b));
+#else
+       return make_float4(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x, 0.0f);
+#endif
 }
 
 __device_inline float4 min(float4 a, float4 b)
 {
+#ifdef __KERNEL_SSE__
+       return _mm_min_ps(a.m128, b.m128);
+#else
        return make_float4(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w));
+#endif
 }
 
 __device_inline float4 max(float4 a, float4 b)
 {
+#ifdef __KERNEL_SSE__
+       return _mm_max_ps(a.m128, b.m128);
+#else
        return make_float4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w));
+#endif
 }
 
 #endif
 
 #ifndef __KERNEL_GPU__
 
+__device_inline float4 select(const int4& mask, const float4& a, const float4& b)
+{
+#ifdef __KERNEL_SSE__
+       /* blendv is sse4, and apparently broken on vs2008 */
+       return _mm_or_ps(_mm_and_ps(_mm_cvtepi32_ps(mask), a), _mm_andnot_ps(_mm_cvtepi32_ps(mask), b)); /* todo: avoid cvt */
+#else
+       return make_float4((mask.x)? a.x: b.x, (mask.y)? a.y: b.y, (mask.z)? a.z: b.z, (mask.w)? a.w: b.w);
+#endif
+}
+
+__device_inline float4 reduce_min(const float4& a)
+{
+#ifdef __KERNEL_SSE__
+       float4 h = min(shuffle<1,0,3,2>(a), a);
+       return min(shuffle<2,3,0,1>(h), h);
+#else
+       return make_float4(min(min(a.x, a.y), min(a.z, a.w)));
+#endif
+}
+
+__device_inline float4 reduce_max(const float4& a)
+{
+#ifdef __KERNEL_SSE__
+       float4 h = max(shuffle<1,0,3,2>(a), a);
+       return max(shuffle<2,3,0,1>(h), h);
+#else
+       return make_float4(max(max(a.x, a.y), max(a.z, a.w)));
+#endif
+}
+
+#if 0
+__device_inline float4 reduce_add(const float4& a)
+{
+#ifdef __KERNEL_SSE__
+       float4 h = shuffle<1,0,3,2>(a) + a;
+       return shuffle<2,3,0,1>(h) + h;
+#else
+       return make_float4((a.x + a.y) + (a.z + a.w));
+#endif
+}
+#endif
+
 __device_inline void print_float4(const char *label, const float4& a)
 {
        printf("%s: %.8f %.8f %.8f %.8f\n", label, a.x, a.y, a.z, a.w);
@@ -685,26 +790,77 @@ __device_inline void print_float4(const char *label, const float4& a)
 
 #endif
 
+#ifndef __KERNEL_OPENCL__
+
+__device_inline bool is_zero(const float4& a)
+{
+#ifdef __KERNEL_SSE__
+       return a == make_float4(0.0f);
+#else
+       return (a.x == 0.0f && a.y == 0.0f && a.z == 0.0f && a.w == 0.0f);
+#endif
+}
+
+__device_inline float reduce_add(const float4& a)
+{
+#ifdef __KERNEL_SSE__
+       float4 h = shuffle<1,0,3,2>(a) + a;
+       return _mm_cvtss_f32(shuffle<2,3,0,1>(h) + h); /* todo: efficiency? */
+#else
+       return ((a.x + a.y) + (a.z + a.w));
+#endif
+}
+
+__device_inline float average(const float4& a)
+{
+       return reduce_add(a) * 0.25f;
+}
+
+__device_inline float dot(const float4& a, const float4& b)
+{
+       return reduce_add(a * b);
+}
+
+#endif
+
 /* Int3 */
 
 #ifndef __KERNEL_OPENCL__
 
+__device_inline int3 min(int3 a, int3 b)
+{
+#ifdef __KERNEL_SSE__
+       return _mm_min_epi32(a.m128, b.m128);
+#else
+       return make_int3(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
+#endif
+}
+
 __device_inline int3 max(int3 a, int3 b)
 {
-       int3 r = {max(a.x, b.x), max(a.y, b.y), max(a.z, b.z)};
-       return r;
+#ifdef __KERNEL_SSE__
+       return _mm_max_epi32(a.m128, b.m128);
+#else
+       return make_int3(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
+#endif
 }
 
 __device_inline int3 clamp(const int3& a, int mn, int mx)
 {
-       int3 r = {clamp(a.x, mn, mx), clamp(a.y, mn, mx), clamp(a.z, mn, mx)};
-       return r;
+#ifdef __KERNEL_SSE__
+       return min(max(a, make_int3(mn)), make_int3(mx));
+#else
+       return make_int3(clamp(a.x, mn, mx), clamp(a.y, mn, mx), clamp(a.z, mn, mx));
+#endif
 }
 
 __device_inline int3 clamp(const int3& a, int3& mn, int mx)
 {
-       int3 r = {clamp(a.x, mn.x, mx), clamp(a.y, mn.y, mx), clamp(a.z, mn.z, mx)};
-       return r;
+#ifdef __KERNEL_SSE__
+       return min(max(a, mn), make_int3(mx));
+#else
+       return make_int3(clamp(a.x, mn.x, mx), clamp(a.y, mn.y, mx), clamp(a.z, mn.z, mx));
+#endif
 }
 
 #endif
@@ -720,16 +876,63 @@ __device_inline void print_int3(const char *label, const int3& a)
 
 /* Int4 */
 
-#ifndef __KERNEL_OPENCL__
+#ifndef __KERNEL_GPU__
 
-__device_inline int4 operator>=(float4 a, float4 b)
+__device_inline int4 operator+(const int4& a, const int4& b)
 {
-       return make_int4(a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w);
+#ifdef __KERNEL_SSE__
+       return _mm_add_epi32(a.m128, b.m128);
+#else
+       return make_int4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
+#endif
+}
+
+__device_inline int4 operator+=(int4& a, const int4& b)
+{
+       return a = a + b;
 }
 
+__device_inline int4 operator>>(const int4& a, int i)
+{
+#ifdef __KERNEL_SSE__
+       return _mm_srai_epi32(a.m128, i);
+#else
+       return make_int4(a.x >> i, a.y >> i, a.z >> i, a.w >> i);
 #endif
+}
 
-#ifndef __KERNEL_GPU__
+__device_inline int4 min(int4 a, int4 b)
+{
+#ifdef __KERNEL_SSE__
+       return _mm_min_epi32(a.m128, b.m128);
+#else
+       return make_int4(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z), min(a.w, b.w));
+#endif
+}
+
+__device_inline int4 max(int4 a, int4 b)
+{
+#ifdef __KERNEL_SSE__
+       return _mm_max_epi32(a.m128, b.m128);
+#else
+       return make_int4(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z), max(a.w, b.w));
+#endif
+}
+
+__device_inline int4 clamp(const int4& a, const int4& mn, const int4& mx)
+{
+       return min(max(a, mn), mx);
+}
+
+__device_inline int4 select(const int4& mask, const int4& a, const int4& b)
+{
+#ifdef __KERNEL_SSE__
+       __m128 m = _mm_cvtepi32_ps(mask);
+       return _mm_castps_si128(_mm_or_ps(_mm_and_ps(m, _mm_castsi128_ps(a)), _mm_andnot_ps(m, _mm_castsi128_ps(b)))); /* todo: avoid cvt */
+#else
+       return make_int4((mask.x)? a.x: b.x, (mask.y)? a.y: b.y, (mask.z)? a.z: b.z, (mask.w)? a.w: b.w);
+#endif
+}
 
 __device_inline void print_int4(const char *label, const int4& a)
 {
index 6836be203f5791adb9889adf2db013797d57b229..3d15b342fe5eaf178c45d9c1ff3639e401774d81 100644 (file)
@@ -69,133 +69,6 @@ protected:
        bool joined;
 };
 
-/* Thread Safe Queue to pass&nbs