Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--build_files/buildbot/slave_compile.py11
-rw-r--r--build_files/cmake/macros.cmake11
-rw-r--r--extern/Eigen3/README.blender6
-rw-r--r--extern/binreloc/README.blender6
-rw-r--r--extern/carve/README.blender4
-rw-r--r--extern/libopenjpeg/README.blender5
-rw-r--r--extern/rangetree/README.blender5
-rw-r--r--extern/xdnd/README.blender8
-rw-r--r--intern/cycles/app/cycles_xml.cpp222
-rw-r--r--intern/cycles/blender/blender_camera.cpp12
-rw-r--r--intern/cycles/blender/blender_curves.cpp59
-rw-r--r--intern/cycles/blender/blender_mesh.cpp41
-rw-r--r--intern/cycles/blender/blender_shader.cpp209
-rw-r--r--intern/cycles/blender/blender_util.h3
-rw-r--r--intern/cycles/bvh/bvh.cpp28
-rw-r--r--intern/cycles/bvh/bvh_build.cpp30
-rw-r--r--intern/cycles/bvh/bvh_split.cpp19
-rw-r--r--intern/cycles/device/device_cpu.cpp4
-rw-r--r--intern/cycles/device/device_cuda.cpp4
-rw-r--r--intern/cycles/device/device_multi.cpp4
-rw-r--r--intern/cycles/device/device_network.cpp4
-rw-r--r--intern/cycles/device/device_opencl.cpp85
-rw-r--r--intern/cycles/graph/node.cpp127
-rw-r--r--intern/cycles/graph/node.h10
-rw-r--r--intern/cycles/graph/node_type.cpp38
-rw-r--r--intern/cycles/graph/node_type.h20
-rw-r--r--intern/cycles/graph/node_xml.cpp28
-rw-r--r--intern/cycles/kernel/geom/geom_bvh.h22
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_traversal.h26
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_traversal.h25
-rw-r--r--intern/cycles/kernel/kernel_bake.h20
-rw-r--r--intern/cycles/kernel/kernel_globals.h8
-rw-r--r--intern/cycles/kernel/kernel_path.h54
-rw-r--r--intern/cycles/kernel/kernel_path_branched.h19
-rw-r--r--intern/cycles/kernel/kernel_shadow.h2
-rw-r--r--intern/cycles/kernel/kernel_types.h4
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel.cpp14
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h36
-rw-r--r--intern/cycles/kernel/shaders/node_brick_texture.osl10
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_color.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_float.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_int.osl26
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_normal.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_point.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_string.osl14
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_vector.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_gradient_texture.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_image_texture.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_magic_texture.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_math.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_mix.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_musgrave_texture.osl12
-rw-r--r--intern/cycles/kernel/shaders/node_normal.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_ramp.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_subsurface_scattering.osl6
-rw-r--r--intern/cycles/kernel/shaders/node_voronoi_texture.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_wave_texture.osl6
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h8
-rw-r--r--intern/cycles/kernel/svm/svm_image.h8
-rw-r--r--intern/cycles/kernel/svm/svm_types.h10
-rw-r--r--intern/cycles/render/attribute.cpp20
-rw-r--r--intern/cycles/render/attribute.h6
-rw-r--r--intern/cycles/render/background.cpp5
-rw-r--r--intern/cycles/render/background.h1
-rw-r--r--intern/cycles/render/bake.cpp2
-rw-r--r--intern/cycles/render/camera.cpp184
-rw-r--r--intern/cycles/render/camera.h8
-rw-r--r--intern/cycles/render/curves.h34
-rw-r--r--intern/cycles/render/film.cpp2
-rw-r--r--intern/cycles/render/graph.cpp145
-rw-r--r--intern/cycles/render/graph.h112
-rw-r--r--intern/cycles/render/image.cpp115
-rw-r--r--intern/cycles/render/image.h5
-rw-r--r--intern/cycles/render/integrator.cpp5
-rw-r--r--intern/cycles/render/integrator.h1
-rw-r--r--intern/cycles/render/light.cpp8
-rw-r--r--intern/cycles/render/mesh.cpp228
-rw-r--r--intern/cycles/render/mesh.h61
-rw-r--r--intern/cycles/render/mesh_displace.cpp9
-rw-r--r--intern/cycles/render/nodes.cpp1323
-rw-r--r--intern/cycles/render/nodes.h162
-rw-r--r--intern/cycles/render/object.cpp44
-rw-r--r--intern/cycles/render/object.h6
-rw-r--r--intern/cycles/render/osl.cpp186
-rw-r--r--intern/cycles/render/osl.h7
-rw-r--r--intern/cycles/render/particles.cpp11
-rw-r--r--intern/cycles/render/particles.h2
-rw-r--r--intern/cycles/render/scene.cpp9
-rw-r--r--intern/cycles/render/scene.h8
-rw-r--r--intern/cycles/render/session.cpp2
-rw-r--r--intern/cycles/render/shader.cpp6
-rw-r--r--intern/cycles/render/svm.cpp54
-rw-r--r--intern/cycles/render/svm.h6
-rw-r--r--intern/cycles/subd/subd_dice.cpp21
-rw-r--r--intern/cycles/subd/subd_dice.h2
-rw-r--r--intern/cycles/util/util_string.cpp40
-rw-r--r--intern/cycles/util/util_string.h5
-rw-r--r--intern/cycles/util/util_texture.h66
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp6
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h1
-rw-r--r--intern/opencolorio/gpu_shader_display_transform.glsl2
-rw-r--r--intern/opensubdiv/gpu_shader_opensubd_display.glsl10
-rw-r--r--release/scripts/modules/bpy_types.py8
-rw-r--r--release/scripts/presets/interface_theme/blender_24x.xml2
-rw-r--r--release/scripts/presets/keyconfig/maya.py2
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h8
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c26
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c4
-rw-r--r--source/blender/blenkernel/intern/colortools.c301
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c13
-rw-r--r--source/blender/blenkernel/intern/image.c4
-rw-r--r--source/blender/blenkernel/intern/material.c3
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c471
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c4
-rw-r--r--source/blender/blenlib/BLI_array_store.h66
-rw-r--r--source/blender/blenlib/BLI_stackdefines.h12
-rw-r--r--source/blender/blenlib/CMakeLists.txt2
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c4
-rw-r--r--source/blender/blenlib/intern/BLI_mempool.c21
-rw-r--r--source/blender/blenlib/intern/array_store.c1731
-rw-r--r--source/blender/blenlib/intern/noise.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c8
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c406
-rw-r--r--source/blender/collada/ArmatureExporter.cpp54
-rw-r--r--source/blender/collada/ArmatureExporter.h2
-rw-r--r--source/blender/collada/ArmatureImporter.cpp222
-rw-r--r--source/blender/collada/ArmatureImporter.h24
-rw-r--r--source/blender/collada/ExportSettings.h1
-rw-r--r--source/blender/collada/ExtraTags.cpp23
-rw-r--r--source/blender/collada/ExtraTags.h11
-rw-r--r--source/blender/collada/MeshImporter.cpp39
-rw-r--r--source/blender/collada/collada.cpp6
-rw-r--r--source/blender/collada/collada.h1
-rw-r--r--source/blender/collada/collada_utils.cpp211
-rw-r--r--source/blender/collada/collada_utils.h51
-rw-r--r--source/blender/depsgraph/CMakeLists.txt53
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h8
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h3
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_debug.h3
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h143
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc129
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.h46
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc (renamed from source/blender/depsgraph/util/depsgraph_util_cycle.cc)42
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.h (renamed from source/blender/depsgraph/util/depsgraph_util_cycle.h)11
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc (renamed from source/blender/depsgraph/intern/depsgraph_build_nodes.cc)43
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h153
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc (renamed from source/blender/depsgraph/util/depsgraph_util_pchanmap.cc)28
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h (renamed from source/blender/depsgraph/util/depsgraph_util_pchanmap.h)15
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc (renamed from source/blender/depsgraph/intern/depsgraph_build_relations.cc)72
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h (renamed from source/blender/depsgraph/intern/depsgraph_build.h)170
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_transitive.cc (renamed from source/blender/depsgraph/util/depsgraph_util_transitive.cc)58
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_transitive.h (renamed from source/blender/depsgraph/util/depsgraph_util_transitive.h)10
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc588
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc115
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h47
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc314
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc1054
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc380
-rw-r--r--source/blender/depsgraph/intern/depsgraph_intern.h95
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc156
-rw-r--r--source/blender/depsgraph/intern/depsgraph_queue.cc177
-rw-r--r--source/blender/depsgraph/intern/depsgraph_queue.h91
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc194
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type_defines.cc123
-rw-r--r--source/blender/depsgraph/intern/depsgraph_types.h252
-rw-r--r--source/blender/depsgraph/intern/depsnode_opcodes.h145
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc409
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.h52
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_debug.cc249
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_debug.h (renamed from source/blender/depsgraph/intern/depsgraph_debug.h)28
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc224
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.h49
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.cc (renamed from source/blender/depsgraph/intern/depsnode.cc)158
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node.h (renamed from source/blender/depsgraph/intern/depsnode.h)41
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.cc (renamed from source/blender/depsgraph/intern/depsnode_component.cc)216
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.h (renamed from source/blender/depsgraph/intern/depsnode_component.h)85
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_operation.cc (renamed from source/blender/depsgraph/intern/depsnode_operation.cc)31
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_operation.h (renamed from source/blender/depsgraph/intern/depsnode_operation.h)42
-rw-r--r--source/blender/depsgraph/util/deg_util_foreach.h68
-rw-r--r--source/blender/depsgraph/util/deg_util_function.h (renamed from source/blender/depsgraph/util/depsgraph_util_function.h)8
-rw-r--r--source/blender/depsgraph/util/deg_util_hash.h (renamed from source/blender/depsgraph/util/depsgraph_util_set.h)43
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_hash.h72
-rw-r--r--source/blender/depsgraph/util/depsgraph_util_map.h67
-rw-r--r--source/blender/editors/animation/anim_deps.c8
-rw-r--r--source/blender/editors/animation/drivers.c5
-rw-r--r--source/blender/editors/animation/keyframing.c24
-rw-r--r--source/blender/editors/armature/armature_utils.c9
-rw-r--r--source/blender/editors/interface/interface_regions.c8
-rw-r--r--source/blender/editors/io/io_collada.c10
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt1
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c726
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c136
-rw-r--r--source/blender/editors/transform/transform.c2
-rw-r--r--source/blender/editors/transform/transform.h13
-rw-r--r--source/blender/editors/transform/transform_generics.c61
-rw-r--r--source/blender/editors/transform/transform_snap.c12
-rw-r--r--source/blender/gpu/GPU_buffers.h5
-rw-r--r--source/blender/gpu/GPU_shader.h1
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c6
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c4
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c8
-rw-r--r--source/blender/gpu/intern/gpu_material.c3
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_frag.glsl18
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_geom.glsl130
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl8
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_geometry.glsl4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl1045
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex.glsl62
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl2
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h8
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h2
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_access.c66
-rw-r--r--source/blender/makesrna/intern/rna_camera.c4
-rw-r--r--source/blender/makesrna/intern/rna_curve.c18
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c1
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c1
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_camera.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c36
-rw-r--r--source/blender/python/intern/bpy_rna.c18
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.h2
-rw-r--r--source/blender/windowmanager/WM_api.h1
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c11
-rw-r--r--source/blender/windowmanager/wm_event_types.h23
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c1
-rw-r--r--tests/gtests/blenlib/BLI_array_store_test.cc815
-rw-r--r--tests/gtests/blenlib/BLI_ghash_performance_test.cc111
-rw-r--r--tests/gtests/blenlib/CMakeLists.txt1
238 files changed, 11364 insertions, 6853 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2b40b9268fc..b558fe14820 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1959,7 +1959,7 @@ elseif(WIN32)
set(OPENAL ${LIBDIR}/openal)
set(OPENALDIR ${LIBDIR}/openal)
set(OPENAL_INCLUDE_DIR ${OPENAL}/include)
- if(MSVC12)
+ if(MSVC)
set(OPENAL_LIBRARY openal32)
else()
set(OPENAL_LIBRARY wrap_oal)
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index 5e25d9f3f04..9a874e92c80 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -75,11 +75,18 @@ if 'cmake' in builder:
cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-hack/bin/nvcc')
elif builder.startswith('win'):
+ if builder.endswith('_vc2015'):
if builder.startswith('win64'):
- cmake_options.append(['-G', '"Visual Studio 12 2013 Win64"'])
+ cmake_options.extend(['-G', 'Visual Studio 14 2015 Win64'])
elif builder.startswith('win32'):
bits = 32
- cmake_options.append(['-G', '"Visual Studio 12 2013"'])
+ cmake_options.extend(['-G', 'Visual Studio 14 2015'])
+ else:
+ if builder.startswith('win64'):
+ cmake_options.extend(['-G', 'Visual Studio 12 2013 Win64'])
+ elif builder.startswith('win32'):
+ bits = 32
+ cmake_options.extend(['-G', 'Visual Studio 12 2013'])
elif builder.startswith('linux'):
tokens = builder.split("_")
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 47fc86c4f20..d34b55e14e0 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -879,8 +879,16 @@ macro(TEST_SHARED_PTR_SUPPORT)
# otherwise it's assumed to be defined in std namespace.
include(CheckIncludeFileCXX)
+ include(CheckCXXSourceCompiles)
set(SHARED_PTR_FOUND FALSE)
- CHECK_INCLUDE_FILE_CXX(memory HAVE_STD_MEMORY_HEADER)
+ # Workaround for newer GCC (6.x+) where C++11 was enabled by default, which lead us
+ # to a situation when there is <unordered_map> include but which can't be used uless
+ # C++11 is enabled.
+ if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "6.0") AND (NOT WITH_CXX11))
+ set(HAVE_STD_MEMORY_HEADER False)
+ else()
+ CHECK_INCLUDE_FILE_CXX(memory HAVE_STD_MEMORY_HEADER)
+ endif()
if(HAVE_STD_MEMORY_HEADER)
# Finding the memory header doesn't mean that shared_ptr is in std
# namespace.
@@ -888,7 +896,6 @@ macro(TEST_SHARED_PTR_SUPPORT)
# In particular, MSVC 2008 has shared_ptr declared in std::tr1. In
# order to support this, we do an extra check to see which namespace
# should be used.
- include(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES("#include <memory>
int main() {
std::shared_ptr<int> int_ptr;
diff --git a/extern/Eigen3/README.blender b/extern/Eigen3/README.blender
new file mode 100644
index 00000000000..8ccc46ac344
--- /dev/null
+++ b/extern/Eigen3/README.blender
@@ -0,0 +1,6 @@
+Project: Eigen, template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms
+URL: http://eigen.tuxfamily.org/index.php?title=Main_Page
+License: GPLv3+
+Upstream version: 3.2.7
+Local modifications:
+- OpenMP fix for MSVC2015, see http://eigen.tuxfamily.org/bz/show_bug.cgi?id=1131
diff --git a/extern/binreloc/README.blender b/extern/binreloc/README.blender
new file mode 100644
index 00000000000..a90b44216a4
--- /dev/null
+++ b/extern/binreloc/README.blender
@@ -0,0 +1,6 @@
+Project: AutoPackage
+URL: http://autopackage.org/docs/binreloc (original, defunct)
+ http://alien.cern.ch/cache/autopackage-1.0/site/docs/binreloc/ (cache)
+License: Public Domain
+Upstream version: Unknown (Last Release)
+Local modifications: None
diff --git a/extern/carve/README.blender b/extern/carve/README.blender
new file mode 100644
index 00000000000..80be40ae558
--- /dev/null
+++ b/extern/carve/README.blender
@@ -0,0 +1,4 @@
+Project: Carve, CSG library
+URL: https://code.google.com/archive/p/carve/
+Upstream version 9a85d733a43d
+Local modifications: See patches/ folder
diff --git a/extern/libopenjpeg/README.blender b/extern/libopenjpeg/README.blender
new file mode 100644
index 00000000000..5aa213c7707
--- /dev/null
+++ b/extern/libopenjpeg/README.blender
@@ -0,0 +1,5 @@
+Project: OpenJPEG
+URL: http://www.openjpeg.org
+License: BSD 2-Clause
+Upstream version: 1.5.2
+Local modifications:
diff --git a/extern/rangetree/README.blender b/extern/rangetree/README.blender
new file mode 100644
index 00000000000..cb5967137ac
--- /dev/null
+++ b/extern/rangetree/README.blender
@@ -0,0 +1,5 @@
+Project: RangeTree
+URL: https://github.com/nicholasbishop/RangeTree
+License: GPLv2+
+Upstream version: c4ecf6bb7dfd
+Local modifications: None
diff --git a/extern/xdnd/README.blender b/extern/xdnd/README.blender
new file mode 100644
index 00000000000..05afe566bba
--- /dev/null
+++ b/extern/xdnd/README.blender
@@ -0,0 +1,8 @@
+Project: X Drag and Drop
+URL: http://www.newplanetsoftware.com/xdnd/ (defunct)
+ https://freedesktop.org/wiki/Specifications/XDND/ (cache)
+License: GPLv2+
+Upstream version: 2000-08-08
+Local modifications:
+* Fix T33192
+ Opening Blender breaks drag-and-drop support on the KDE desktop.
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index f734d01f71d..9f967a4bde9 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -31,6 +31,7 @@
#include "mesh.h"
#include "nodes.h"
#include "object.h"
+#include "osl.h"
#include "shader.h"
#include "scene.h"
@@ -214,25 +215,7 @@ static bool xml_equal_string(pugi::xml_node node, const char *name, const char *
return false;
}
-static bool xml_read_enum(ustring *str, ShaderEnum& enm, pugi::xml_node node, const char *name)
-{
- pugi::xml_attribute attr = node.attribute(name);
-
- if(attr) {
- ustring ustr(attr.value());
-
- if(enm.exists(ustr)) {
- *str = ustr;
- return true;
- }
- else
- fprintf(stderr, "Unknown value \"%s\" for attribute \"%s\".\n", ustr.c_str(), name);
- }
-
- return false;
-}
-
-static bool xml_read_enum_value(int *value, ShaderEnum& enm, pugi::xml_node node, const char *name)
+static bool xml_read_enum_value(int *value, NodeEnum& enm, pugi::xml_node node, const char *name)
{
pugi::xml_attribute attr = node.attribute(name);
@@ -250,77 +233,16 @@ static bool xml_read_enum_value(int *value, ShaderEnum& enm, pugi::xml_node node
return false;
}
-static ShaderSocketType xml_read_socket_type(pugi::xml_node node, const char *name)
-{
- pugi::xml_attribute attr = node.attribute(name);
-
- if(attr) {
- string value = attr.value();
- if(string_iequals(value, "float"))
- return SHADER_SOCKET_FLOAT;
- else if(string_iequals(value, "int"))
- return SHADER_SOCKET_INT;
- else if(string_iequals(value, "color"))
- return SHADER_SOCKET_COLOR;
- else if(string_iequals(value, "vector"))
- return SHADER_SOCKET_VECTOR;
- else if(string_iequals(value, "point"))
- return SHADER_SOCKET_POINT;
- else if(string_iequals(value, "normal"))
- return SHADER_SOCKET_NORMAL;
- else if(string_iequals(value, "closure color"))
- return SHADER_SOCKET_CLOSURE;
- else if(string_iequals(value, "string"))
- return SHADER_SOCKET_STRING;
- else
- fprintf(stderr, "Unknown shader socket type \"%s\" for attribute \"%s\".\n", value.c_str(), name);
- }
-
- return SHADER_SOCKET_UNDEFINED;
-}
-
/* Camera */
-static void xml_read_camera(const XMLReadState& state, pugi::xml_node node)
+static void xml_read_camera(XMLReadState& state, pugi::xml_node node)
{
Camera *cam = state.scene->camera;
xml_read_int(&cam->width, node, "width");
xml_read_int(&cam->height, node, "height");
- if(xml_read_float(&cam->fov, node, "fov"))
- cam->fov = DEG2RADF(cam->fov);
-
- xml_read_float(&cam->nearclip, node, "nearclip");
- xml_read_float(&cam->farclip, node, "farclip");
- xml_read_float(&cam->aperturesize, node, "aperturesize"); // 0.5*focallength/fstop
- xml_read_float(&cam->focaldistance, node, "focaldistance");
- xml_read_float(&cam->shuttertime, node, "shuttertime");
- xml_read_float(&cam->aperture_ratio, node, "aperture_ratio");
-
- if(xml_equal_string(node, "type", "orthographic"))
- cam->type = CAMERA_ORTHOGRAPHIC;
- else if(xml_equal_string(node, "type", "perspective"))
- cam->type = CAMERA_PERSPECTIVE;
- else if(xml_equal_string(node, "type", "panorama"))
- cam->type = CAMERA_PANORAMA;
-
- if(xml_equal_string(node, "panorama_type", "equirectangular"))
- cam->panorama_type = PANORAMA_EQUIRECTANGULAR;
- else if(xml_equal_string(node, "panorama_type", "fisheye_equidistant"))
- cam->panorama_type = PANORAMA_FISHEYE_EQUIDISTANT;
- else if(xml_equal_string(node, "panorama_type", "fisheye_equisolid"))
- cam->panorama_type = PANORAMA_FISHEYE_EQUISOLID;
-
- xml_read_float(&cam->fisheye_fov, node, "fisheye_fov");
- xml_read_float(&cam->fisheye_lens, node, "fisheye_lens");
-
- xml_read_bool(&cam->use_spherical_stereo, node, "use_spherical_stereo");
- xml_read_float(&cam->interocular_distance, node, "interocular_distance");
- xml_read_float(&cam->convergence_distance, node, "convergence_distance");
-
- xml_read_float(&cam->sensorwidth, node, "sensorwidth");
- xml_read_float(&cam->sensorheight, node, "sensorheight");
+ xml_read_node(state, cam, node);
cam->matrix = state.tfm;
@@ -345,6 +267,7 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
{
xml_read_node(state, shader, graph_node);
+ ShaderManager *manager = state.scene->shader_manager;
ShaderGraph *graph = new ShaderGraph();
map<string, ShaderNode*> nodemap;
@@ -364,8 +287,8 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
xml_read_string(&img->filename, node, "src");
img->filename = path_join(state.base, img->filename);
- xml_read_enum(&img->color_space, ImageTextureNode::color_space_enum, node, "color_space");
- xml_read_enum(&img->projection, ImageTextureNode::projection_enum, node, "projection");
+ xml_read_enum_value((int*)&img->color_space, ImageTextureNode::color_space_enum, node, "color_space");
+ xml_read_enum_value((int*)&img->projection, ImageTextureNode::projection_enum, node, "projection");
xml_read_float(&img->projection_blend, node, "projection_blend");
/* ToDo: Interpolation */
@@ -378,56 +301,40 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
xml_read_string(&env->filename, node, "src");
env->filename = path_join(state.base, env->filename);
- xml_read_enum(&env->color_space, EnvironmentTextureNode::color_space_enum, node, "color_space");
- xml_read_enum(&env->projection, EnvironmentTextureNode::projection_enum, node, "projection");
+ xml_read_enum_value((int*)&env->color_space, EnvironmentTextureNode::color_space_enum, node, "color_space");
+ xml_read_enum_value((int*)&env->projection, EnvironmentTextureNode::projection_enum, node, "projection");
snode = env;
}
+#ifdef WITH_OSL
else if(string_iequals(node.name(), "osl_shader")) {
- OSLScriptNode *osl = new OSLScriptNode();
+ if(manager->use_osl()) {
+ std::string filepath;
- /* Source */
- xml_read_string(&osl->filepath, node, "src");
- if(path_is_relative(osl->filepath)) {
- osl->filepath = path_join(state.base, osl->filepath);
- }
+ if(xml_read_string(&filepath, node, "src")) {
+ if(path_is_relative(filepath)) {
+ filepath = path_join(state.base, filepath);
+ }
- /* Generate inputs/outputs from node sockets
- *
- * Note: ShaderInput/ShaderOutput store shallow string copies only!
- * So we register them as ustring to ensure the pointer stays valid. */
- /* read input values */
- for(pugi::xml_node param = node.first_child(); param; param = param.next_sibling()) {
- if(string_iequals(param.name(), "input")) {
- string name;
- if(!xml_read_string(&name, param, "name"))
- continue;
-
- ShaderSocketType type = xml_read_socket_type(param, "type");
- if(type == SHADER_SOCKET_UNDEFINED)
- continue;
-
- osl->add_input(ustring(name).c_str(), type);
+ snode = ((OSLShaderManager*)manager)->osl_node(filepath);
+
+ if(!snode) {
+ fprintf(stderr, "Failed to create OSL node from \"%s\".\n", filepath.c_str());
+ }
}
- else if(string_iequals(param.name(), "output")) {
- string name;
- if(!xml_read_string(&name, param, "name"))
- continue;
-
- ShaderSocketType type = xml_read_socket_type(param, "type");
- if(type == SHADER_SOCKET_UNDEFINED)
- continue;
-
- osl->add_output(ustring(name).c_str(), type);
+ else {
+ fprintf(stderr, "OSL node missing \"src\" attribute.\n");
}
}
-
- snode = osl;
+ else {
+ fprintf(stderr, "OSL node without using --shadingsys osl.\n");
+ }
}
+#endif
else if(string_iequals(node.name(), "sky_texture")) {
SkyTextureNode *sky = new SkyTextureNode();
- xml_read_enum(&sky->type, SkyTextureNode::type_enum, node, "type");
+ xml_read_enum_value((int*)&sky->type, SkyTextureNode::type_enum, node, "type");
xml_read_float3(&sky->sun_direction, node, "sun_direction");
xml_read_float(&sky->turbidity, node, "turbidity");
xml_read_float(&sky->ground_albedo, node, "ground_albedo");
@@ -452,17 +359,17 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
}
else if(string_iequals(node.name(), "gradient_texture")) {
GradientTextureNode *blend = new GradientTextureNode();
- xml_read_enum(&blend->type, GradientTextureNode::type_enum, node, "type");
+ xml_read_enum_value((int*)&blend->type, GradientTextureNode::type_enum, node, "type");
snode = blend;
}
else if(string_iequals(node.name(), "voronoi_texture")) {
VoronoiTextureNode *voronoi = new VoronoiTextureNode();
- xml_read_enum(&voronoi->coloring, VoronoiTextureNode::coloring_enum, node, "coloring");
+ xml_read_enum_value((int*)&voronoi->coloring, VoronoiTextureNode::coloring_enum, node, "coloring");
snode = voronoi;
}
else if(string_iequals(node.name(), "musgrave_texture")) {
MusgraveTextureNode *musgrave = new MusgraveTextureNode();
- xml_read_enum(&musgrave->type, MusgraveTextureNode::type_enum, node, "type");
+ xml_read_enum_value((int*)&musgrave->type, MusgraveTextureNode::type_enum, node, "type");
snode = musgrave;
}
else if(string_iequals(node.name(), "magic_texture")) {
@@ -472,8 +379,8 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
}
else if(string_iequals(node.name(), "wave_texture")) {
WaveTextureNode *wave = new WaveTextureNode();
- xml_read_enum(&wave->type, WaveTextureNode::type_enum, node, "type");
- xml_read_enum(&wave->profile, WaveTextureNode::profile_enum, node, "profile");
+ xml_read_enum_value((int*)&wave->type, WaveTextureNode::type_enum, node, "type");
+ xml_read_enum_value((int*)&wave->profile, WaveTextureNode::profile_enum, node, "profile");
snode = wave;
}
else if(string_iequals(node.name(), "normal")) {
@@ -508,7 +415,7 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
}
else if(string_iequals(node.name(), "anisotropic_bsdf")) {
AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();
- xml_read_enum(&aniso->distribution, AnisotropicBsdfNode::distribution_enum, node, "distribution");
+ xml_read_enum_value((int*)&aniso->distribution, AnisotropicBsdfNode::distribution_enum, node, "distribution");
snode = aniso;
}
else if(string_iequals(node.name(), "diffuse_bsdf")) {
@@ -525,27 +432,27 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
}
else if(string_iequals(node.name(), "toon_bsdf")) {
ToonBsdfNode *toon = new ToonBsdfNode();
- xml_read_enum(&toon->component, ToonBsdfNode::component_enum, node, "component");
+ xml_read_enum_value((int*)&toon->component, ToonBsdfNode::component_enum, node, "component");
snode = toon;
}
else if(string_iequals(node.name(), "glossy_bsdf")) {
GlossyBsdfNode *glossy = new GlossyBsdfNode();
- xml_read_enum(&glossy->distribution, GlossyBsdfNode::distribution_enum, node, "distribution");
+ xml_read_enum_value((int*)&glossy->distribution, GlossyBsdfNode::distribution_enum, node, "distribution");
snode = glossy;
}
else if(string_iequals(node.name(), "glass_bsdf")) {
GlassBsdfNode *diel = new GlassBsdfNode();
- xml_read_enum(&diel->distribution, GlassBsdfNode::distribution_enum, node, "distribution");
+ xml_read_enum_value((int*)&diel->distribution, GlassBsdfNode::distribution_enum, node, "distribution");
snode = diel;
}
else if(string_iequals(node.name(), "refraction_bsdf")) {
RefractionBsdfNode *diel = new RefractionBsdfNode();
- xml_read_enum(&diel->distribution, RefractionBsdfNode::distribution_enum, node, "distribution");
+ xml_read_enum_value((int*)&diel->distribution, RefractionBsdfNode::distribution_enum, node, "distribution");
snode = diel;
}
else if(string_iequals(node.name(), "hair_bsdf")) {
HairBsdfNode *hair = new HairBsdfNode();
- xml_read_enum(&hair->component, HairBsdfNode::component_enum, node, "component");
+ xml_read_enum_value((int*)&hair->component, HairBsdfNode::component_enum, node, "component");
snode = hair;
}
else if(string_iequals(node.name(), "emission")) {
@@ -623,7 +530,7 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
else if(string_iequals(node.name(), "mix")) {
/* ToDo: Tag Mix case for optimization */
MixNode *mix = new MixNode();
- xml_read_enum(&mix->type, MixNode::type_enum, node, "type");
+ xml_read_enum_value((int*)&mix->type, MixNode::type_enum, node, "type");
xml_read_bool(&mix->use_clamp, node, "use_clamp");
snode = mix;
}
@@ -687,32 +594,32 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
else if(string_iequals(node.name(), "normal_map")) {
NormalMapNode *nmap = new NormalMapNode;
xml_read_ustring(&nmap->attribute, node, "attribute");
- xml_read_enum(&nmap->space, NormalMapNode::space_enum, node, "space");
+ xml_read_enum_value((int*)&nmap->space, NormalMapNode::space_enum, node, "space");
snode = nmap;
}
else if(string_iequals(node.name(), "tangent")) {
TangentNode *tangent = new TangentNode;
xml_read_ustring(&tangent->attribute, node, "attribute");
- xml_read_enum(&tangent->direction_type, TangentNode::direction_type_enum, node, "direction_type");
- xml_read_enum(&tangent->axis, TangentNode::axis_enum, node, "axis");
+ xml_read_enum_value((int*)&tangent->direction_type, TangentNode::direction_type_enum, node, "direction_type");
+ xml_read_enum_value((int*)&tangent->axis, TangentNode::axis_enum, node, "axis");
snode = tangent;
}
else if(string_iequals(node.name(), "math")) {
MathNode *math = new MathNode();
- xml_read_enum(&math->type, MathNode::type_enum, node, "type");
+ xml_read_enum_value((int*)&math->type, MathNode::type_enum, node, "type");
xml_read_bool(&math->use_clamp, node, "use_clamp");
snode = math;
}
else if(string_iequals(node.name(), "vector_math")) {
VectorMathNode *vmath = new VectorMathNode();
- xml_read_enum(&vmath->type, VectorMathNode::type_enum, node, "type");
+ xml_read_enum_value((int*)&vmath->type, VectorMathNode::type_enum, node, "type");
snode = vmath;
}
else if(string_iequals(node.name(), "vector_transform")) {
VectorTransformNode *vtransform = new VectorTransformNode();
- xml_read_enum(&vtransform->type, VectorTransformNode::type_enum, node, "type");
- xml_read_enum(&vtransform->convert_from, VectorTransformNode::convert_space_enum, node, "convert_from");
- xml_read_enum(&vtransform->convert_to, VectorTransformNode::convert_space_enum, node, "convert_to");
+ xml_read_enum_value((int*)&vtransform->type, VectorTransformNode::type_enum, node, "type");
+ xml_read_enum_value((int*)&vtransform->convert_from, VectorTransformNode::convert_space_enum, node, "convert_from");
+ xml_read_enum_value((int*)&vtransform->convert_to, VectorTransformNode::convert_space_enum, node, "convert_to");
snode = vtransform;
}
else if(string_iequals(node.name(), "connect")) {
@@ -731,7 +638,7 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
ShaderNode *fromnode = nodemap[from_tokens[0]];
foreach(ShaderOutput *out, fromnode->outputs)
- if(string_iequals(xml_socket_name(out->name), from_tokens[1]))
+ if(string_iequals(xml_socket_name(out->name().c_str()), from_tokens[1]))
output = out;
if(!output)
@@ -744,7 +651,7 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
ShaderNode *tonode = nodemap[to_tokens[0]];
foreach(ShaderInput *in, tonode->inputs)
- if(string_iequals(xml_socket_name(in->name), to_tokens[1]))
+ if(string_iequals(xml_socket_name(in->name().c_str()), to_tokens[1]))
input = in;
if(!input)
@@ -776,20 +683,20 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
/* read input values */
for(pugi::xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute()) {
foreach(ShaderInput *in, snode->inputs) {
- if(string_iequals(in->name, attr.name())) {
- switch(in->type) {
- case SHADER_SOCKET_FLOAT:
- case SHADER_SOCKET_INT:
- xml_read_float(&in->value.x, node, attr.name());
+ if(string_iequals(in->name().c_str(), attr.name())) {
+ switch(in->type()) {
+ case SocketType::FLOAT:
+ case SocketType::INT:
+ xml_read_float(&in->value_float(), node, attr.name());
break;
- case SHADER_SOCKET_COLOR:
- case SHADER_SOCKET_VECTOR:
- case SHADER_SOCKET_POINT:
- case SHADER_SOCKET_NORMAL:
- xml_read_float3(&in->value, node, attr.name());
+ case SocketType::COLOR:
+ case SocketType::VECTOR:
+ case SocketType::POINT:
+ case SocketType::NORMAL:
+ xml_read_float3(&in->value(), node, attr.name());
break;
- case SHADER_SOCKET_STRING:
- xml_read_ustring( &in->value_string, node, attr.name() );
+ case SocketType::STRING:
+ xml_read_ustring( &in->value_string(), node, attr.name() );
break;
default:
break;
@@ -908,6 +815,11 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node)
/* create vertices */
mesh->verts = P;
+ size_t num_triangles = 0;
+ for(size_t i = 0; i < nverts.size(); i++)
+ num_triangles += nverts[i]-2;
+ mesh->reserve_mesh(mesh->verts.size(), num_triangles);
+
/* create triangles */
int index_offset = 0;
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index 9dec489ce33..f02fc553908 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -37,7 +37,7 @@ struct BlenderCamera {
float lens;
float shuttertime;
Camera::MotionPosition motion_position;
- float shutter_curve[RAMP_TABLE_SIZE];
+ array<float> shutter_curve;
Camera::RollingShutterType rolling_shutter_type;
float rolling_shutter_duration;
@@ -108,10 +108,6 @@ static void blender_camera_init(BlenderCamera *bcam,
/* render resolution */
bcam->full_width = render_resolution_x(b_render);
bcam->full_height = render_resolution_y(b_render);
-
- /* pixel aspect */
- bcam->pixelaspect.x = b_render.pixel_aspect_x();
- bcam->pixelaspect.y = b_render.pixel_aspect_y();
}
static float blender_camera_focal_distance(BL::RenderEngine& b_engine,
@@ -464,7 +460,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
cam->rolling_shutter_type = bcam->rolling_shutter_type;
cam->rolling_shutter_duration = bcam->rolling_shutter_duration;
- memcpy(cam->shutter_curve, bcam->shutter_curve, sizeof(cam->shutter_curve));
+ cam->shutter_curve = bcam->shutter_curve;
/* border */
cam->border = bcam->border;
@@ -563,6 +559,10 @@ void BlenderSync::sync_camera_motion(BL::RenderSettings& b_render,
float aspectratio, sensor_size;
blender_camera_init(&bcam, b_render);
+ /* TODO(sergey): Consider making it a part of blender_camera_init(). */
+ bcam.pixelaspect.x = b_render.pixel_aspect_x();
+ bcam.pixelaspect.y = b_render.pixel_aspect_y();
+
blender_camera_from_object(&bcam, b_engine, b_ob);
blender_camera_viewplane(&bcam,
width, height,
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 39521c841d1..7b9d4f2ecdf 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -134,10 +134,7 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
}
}
- mesh->verts.reserve(mesh->verts.size() + numverts);
- mesh->triangles.reserve(mesh->triangles.size() + numtris);
- mesh->shader.reserve(mesh->shader.size() + numtris);
- mesh->smooth.reserve(mesh->smooth.size() + numtris);
+ mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);
/* actually export */
for(int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
@@ -157,8 +154,8 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
xbasis = normalize(cross(RotCam - ickey_loc, v1));
float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
- mesh->verts.push_back(ickey_loc_shfl);
- mesh->verts.push_back(ickey_loc_shfr);
+ mesh->add_vertex(ickey_loc_shfl);
+ mesh->add_vertex(ickey_loc_shfr);
vertexindex += 2;
for(int curvekey = CData->curve_firstkey[curve] + 1; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) {
@@ -184,8 +181,8 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
xbasis = normalize(cross(RotCam - ickey_loc, v1));
float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
- mesh->verts.push_back(ickey_loc_shfl);
- mesh->verts.push_back(ickey_loc_shfr);
+ mesh->add_vertex(ickey_loc_shfl);
+ mesh->add_vertex(ickey_loc_shfr);
mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], true);
mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], true);
vertexindex += 2;
@@ -193,7 +190,6 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
}
}
- mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@@ -220,10 +216,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resol
}
}
- mesh->verts.reserve(mesh->verts.size() + numverts);
- mesh->triangles.reserve(mesh->triangles.size() + numtris);
- mesh->shader.reserve(mesh->shader.size() + numtris);
- mesh->smooth.reserve(mesh->smooth.size() + numtris);
+ mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);
/* actually export */
for(int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
@@ -312,7 +305,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resol
float angle = M_2PI_F / (float)resolution;
for(int section = 0; section < resolution; section++) {
float3 ickey_loc_shf = ickey_loc + radius * (cosf(angle * section) * xbasis + sinf(angle * section) * ybasis);
- mesh->verts.push_back(ickey_loc_shf);
+ mesh->add_vertex(ickey_loc_shf);
}
if(subv != 0) {
@@ -329,7 +322,6 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resol
}
}
- mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@@ -344,7 +336,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
int num_keys = 0;
int num_curves = 0;
- if(!(mesh->curves.empty() && mesh->curve_keys.empty()))
+ if(mesh->num_curves())
return;
Attribute *attr_intercept = NULL;
@@ -367,8 +359,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
VLOG(1) << "Exporting curve segments for mesh " << mesh->name;
}
- mesh->curve_keys.reserve(mesh->curve_keys.size() + num_keys);
- mesh->curves.reserve(mesh->curves.size() + num_curves);
+ mesh->reserve_curves(mesh->num_curves() + num_curves, mesh->curve_keys.size() + num_keys);
num_keys = 0;
num_curves = 0;
@@ -396,18 +387,16 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
num_curve_keys++;
}
- mesh->add_curve(num_keys, num_curve_keys, CData->psys_shader[sys]);
+ mesh->add_curve(num_keys, CData->psys_shader[sys]);
num_keys += num_curve_keys;
num_curves++;
}
}
/* check allocation */
- if((mesh->curve_keys.size() != num_keys) || (mesh->curves.size() != num_curves)) {
+ if((mesh->curve_keys.size() != num_keys) || (mesh->num_curves() != num_curves)) {
VLOG(1) << "Allocation failed, clearing data";
- mesh->curve_keys.clear();
- mesh->curves.clear();
- mesh->curve_attributes.clear();
+ mesh->clear();
}
}
@@ -450,13 +439,16 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int
if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
radius = 0.0f;
+ /* curve motion keys store both position and radius in float4 */
mP[i] = float3_to_float4(ickey_loc);
mP[i].w = radius;
/* unlike mesh coordinates, these tend to be slightly different
* between frames due to particle transforms into/out of object
* space, so we use an epsilon to detect actual changes */
- if(len_squared(mP[i] - mesh->curve_keys[i]) > 1e-5f*1e-5f)
+ float4 curve_key = float3_to_float4(mesh->curve_keys[i]);
+ curve_key.w = mesh->curve_radius[i];
+ if(len_squared(mP[i] - curve_key) > 1e-5f*1e-5f)
have_motion = true;
}
@@ -480,8 +472,10 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int
for(int step = 0; step < time_index; step++) {
float4 *mP = attr_mP->data_float4() + step*numkeys;
- for(int key = 0; key < numkeys; key++)
- mP[key] = mesh->curve_keys[key];
+ for(int key = 0; key < numkeys; key++) {
+ mP[key] = float3_to_float4(mesh->curve_keys[key]);
+ mP[key].w = mesh->curve_radius[key];
+ }
}
}
}
@@ -641,7 +635,9 @@ void BlenderSync::sync_curves(Mesh *mesh,
if(!motion) {
/* Clear stored curve data */
mesh->curve_keys.clear();
- mesh->curves.clear();
+ mesh->curve_radius.clear();
+ mesh->curve_first_key.clear();
+ mesh->curve_shader.clear();
mesh->curve_attributes.clear();
}
@@ -658,7 +654,7 @@ void BlenderSync::sync_curves(Mesh *mesh,
int triangle_method = scene->curve_system_manager->triangle_method;
int resolution = scene->curve_system_manager->resolution;
size_t vert_num = mesh->verts.size();
- size_t tri_num = mesh->triangles.size();
+ size_t tri_num = mesh->num_triangles();
int used_res = 1;
/* extract particle hair data - should be combined with connecting to mesh later*/
@@ -714,11 +710,10 @@ void BlenderSync::sync_curves(Mesh *mesh,
else {
Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
float3 *generated = attr_generated->data_float3();
- size_t i = 0;
- foreach(Mesh::Curve& curve, mesh->curves) {
- float3 co = float4_to_float3(mesh->curve_keys[curve.first_key]);
- generated[i++] = co*size - loc;
+ for(size_t i = 0; i < mesh->num_curves(); i++) {
+ float3 co = mesh->curve_keys[mesh->get_curve(i).first_key];
+ generated[i] = co*size - loc;
}
}
}
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 4a0ad79f3ae..80db51148e6 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -548,13 +548,12 @@ static void create_mesh(Scene *scene,
numtris += (vi[3] == 0)? 1: 2;
}
- /* reserve memory */
- mesh->reserve(numverts, numtris, 0, 0);
+ /* allocate memory */
+ mesh->reserve_mesh(numverts, numtris);
/* create vertex coordinates and normals */
- int i = 0;
- for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i)
- mesh->verts[i] = get_float3(v->co());
+ for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
+ mesh->add_vertex(get_float3(v->co()));
Attribute *attr_N = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
float3 *N = attr_N->data_float3();
@@ -583,7 +582,7 @@ static void create_mesh(Scene *scene,
/* create faces */
vector<int> nverts(numfaces);
vector<int> face_flags(numfaces, FACE_FLAG_NONE);
- int fi = 0, ti = 0;
+ int fi = 0;
for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
int4 vi = get_int4(f->vertices_raw());
@@ -618,18 +617,18 @@ static void create_mesh(Scene *scene,
is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])))
{
// TODO(mai): order here is probably wrong
- mesh->set_triangle(ti++, vi[0], vi[1], vi[3], shader, smooth, true);
- mesh->set_triangle(ti++, vi[2], vi[3], vi[1], shader, smooth, true);
+ mesh->add_triangle(vi[0], vi[1], vi[3], shader, smooth, true);
+ mesh->add_triangle(vi[2], vi[3], vi[1], shader, smooth, true);
face_flags[fi] |= FACE_FLAG_DIVIDE_24;
}
else {
- mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth, true);
- mesh->set_triangle(ti++, vi[0], vi[2], vi[3], shader, smooth, true);
+ mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth, true);
+ mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth, true);
face_flags[fi] |= FACE_FLAG_DIVIDE_13;
}
}
else
- mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth, false);
+ mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth, false);
nverts[fi] = n;
}
@@ -759,11 +758,12 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
/* create derived mesh */
PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");
- vector<Mesh::Triangle> oldtriangle = mesh->triangles;
+ array<int> oldtriangle = mesh->triangles;
/* compares curve_keys rather than strands in order to handle quick hair
* adjustments in dynamic BVH - other methods could probably do this better*/
- vector<float4> oldcurve_keys = mesh->curve_keys;
+ array<float3> oldcurve_keys = mesh->curve_keys;
+ array<float> oldcurve_radius = mesh->curve_radius;
mesh->clear();
mesh->used_shaders = used_shaders;
@@ -827,14 +827,21 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
if(oldtriangle.size() != mesh->triangles.size())
rebuild = true;
else if(oldtriangle.size()) {
- if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
+ if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(int)*oldtriangle.size()) != 0)
rebuild = true;
}
if(oldcurve_keys.size() != mesh->curve_keys.size())
rebuild = true;
else if(oldcurve_keys.size()) {
- if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(float4)*oldcurve_keys.size()) != 0)
+ if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(float3)*oldcurve_keys.size()) != 0)
+ rebuild = true;
+ }
+
+ if(oldcurve_radius.size() != mesh->curve_radius.size())
+ rebuild = true;
+ else if(oldcurve_radius.size()) {
+ if(memcmp(&oldcurve_radius[0], &mesh->curve_radius[0], sizeof(float)*oldcurve_radius.size()) != 0)
rebuild = true;
}
@@ -931,8 +938,8 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if(attr_mP) {
- float4 *keys = &mesh->curve_keys[0];
- memcpy(attr_mP->data_float4() + time_index*numkeys, keys, sizeof(float4)*numkeys);
+ float3 *keys = &mesh->curve_keys[0];
+ memcpy(attr_mP->data_float3() + time_index*numkeys, keys, sizeof(float3)*numkeys);
}
}
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index a56c2e75e4e..7a13641a312 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -127,82 +127,57 @@ static float3 get_node_output_vector(BL::Node& b_node, const string& name)
return make_float3(value[0], value[1], value[2]);
}
-static ShaderSocketType convert_socket_type(BL::NodeSocket& b_socket)
+static SocketType::Type convert_socket_type(BL::NodeSocket& b_socket)
{
switch(b_socket.type()) {
case BL::NodeSocket::type_VALUE:
- return SHADER_SOCKET_FLOAT;
+ return SocketType::FLOAT;
case BL::NodeSocket::type_INT:
- return SHADER_SOCKET_INT;
+ return SocketType::INT;
case BL::NodeSocket::type_VECTOR:
- return SHADER_SOCKET_VECTOR;
+ return SocketType::VECTOR;
case BL::NodeSocket::type_RGBA:
- return SHADER_SOCKET_COLOR;
+ return SocketType::COLOR;
case BL::NodeSocket::type_STRING:
- return SHADER_SOCKET_STRING;
+ return SocketType::STRING;
case BL::NodeSocket::type_SHADER:
- return SHADER_SOCKET_CLOSURE;
+ return SocketType::CLOSURE;
default:
- return SHADER_SOCKET_UNDEFINED;
+ return SocketType::UNDEFINED;
}
}
-#ifdef WITH_OSL
-static ShaderSocketType convert_osl_socket_type(OSL::OSLQuery& query,
- BL::NodeSocket& b_socket)
-{
- ShaderSocketType socket_type = convert_socket_type(b_socket);
- if(socket_type == SHADER_SOCKET_VECTOR) {
- /* TODO(sergey): Do we need compatible_name() here? */
- const OSL::OSLQuery::Parameter *param = query.getparam(b_socket.name());
- assert(param != NULL);
- if(param != NULL) {
- if(param->type.vecsemantics == TypeDesc::POINT) {
- socket_type = SHADER_SOCKET_POINT;
- }
- else if(param->type.vecsemantics == TypeDesc::NORMAL) {
- socket_type = SHADER_SOCKET_NORMAL;
- }
- }
- }
-
- return socket_type;
-}
-#endif /* WITH_OSL */
-
static void set_default_value(ShaderInput *input,
BL::NodeSocket& b_sock,
BL::BlendData& b_data,
BL::ID& b_id)
{
/* copy values for non linked inputs */
- switch(input->type) {
- case SHADER_SOCKET_FLOAT: {
+ switch(input->type()) {
+ case SocketType::FLOAT: {
input->set(get_float(b_sock.ptr, "default_value"));
break;
}
- case SHADER_SOCKET_INT: {
- input->set((float)get_int(b_sock.ptr, "default_value"));
+ case SocketType::INT: {
+ input->set(get_int(b_sock.ptr, "default_value"));
break;
}
- case SHADER_SOCKET_COLOR: {
+ case SocketType::COLOR: {
input->set(float4_to_float3(get_float4(b_sock.ptr, "default_value")));
break;
}
- case SHADER_SOCKET_NORMAL:
- case SHADER_SOCKET_POINT:
- case SHADER_SOCKET_VECTOR: {
+ case SocketType::NORMAL:
+ case SocketType::POINT:
+ case SocketType::VECTOR: {
input->set(get_float3(b_sock.ptr, "default_value"));
break;
}
- case SHADER_SOCKET_STRING: {
+ case SocketType::STRING: {
input->set((ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
break;
}
-
- case SHADER_SOCKET_CLOSURE:
- case SHADER_SOCKET_UNDEFINED:
+ default:
break;
}
}
@@ -315,7 +290,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeMixRGB)) {
BL::ShaderNodeMixRGB b_mix_node(b_node);
MixNode *mix = new MixNode();
- mix->type = MixNode::type_enum[b_mix_node.blend_type()];
+ mix->type = (NodeMix)b_mix_node.blend_type();
mix->use_clamp = b_mix_node.use_clamp();
node = mix;
}
@@ -341,27 +316,27 @@ static ShaderNode *add_node(Scene *scene,
node = new HSVNode();
}
else if(b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
- node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
+ node = new RGBToBWNode();
}
else if(b_node.is_a(&RNA_ShaderNodeMath)) {
BL::ShaderNodeMath b_math_node(b_node);
MathNode *math = new MathNode();
- math->type = MathNode::type_enum[b_math_node.operation()];
+ math->type = (NodeMath)b_math_node.operation();
math->use_clamp = b_math_node.use_clamp();
node = math;
}
else if(b_node.is_a(&RNA_ShaderNodeVectorMath)) {
BL::ShaderNodeVectorMath b_vector_math_node(b_node);
VectorMathNode *vmath = new VectorMathNode();
- vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()];
+ vmath->type = (NodeVectorMath)b_vector_math_node.operation();
node = vmath;
}
else if(b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
VectorTransformNode *vtransform = new VectorTransformNode();
- vtransform->type = VectorTransformNode::type_enum[b_vector_transform_node.vector_type()];
- vtransform->convert_from = VectorTransformNode::convert_space_enum[b_vector_transform_node.convert_from()];
- vtransform->convert_to = VectorTransformNode::convert_space_enum[b_vector_transform_node.convert_to()];
+ vtransform->type = (NodeVectorTransformType)b_vector_transform_node.vector_type();
+ vtransform->convert_from = (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_from();
+ vtransform->convert_to = (NodeVectorTransformConvertSpace)b_vector_transform_node.convert_to();
node = vtransform;
}
else if(b_node.is_a(&RNA_ShaderNodeNormal)) {
@@ -410,13 +385,13 @@ static ShaderNode *add_node(Scene *scene,
switch(b_aniso_node.distribution()) {
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
- aniso->distribution = ustring("Beckmann");
+ aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
- aniso->distribution = ustring("GGX");
+ aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
- aniso->distribution = ustring("Ashikhmin-Shirley");
+ aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
break;
}
@@ -432,13 +407,13 @@ static ShaderNode *add_node(Scene *scene,
switch(b_subsurface_node.falloff()) {
case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
- subsurface->closure = CLOSURE_BSSRDF_CUBIC_ID;
+ subsurface->falloff = CLOSURE_BSSRDF_CUBIC_ID;
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN:
- subsurface->closure = CLOSURE_BSSRDF_GAUSSIAN_ID;
+ subsurface->falloff = CLOSURE_BSSRDF_GAUSSIAN_ID;
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
- subsurface->closure = CLOSURE_BSSRDF_BURLEY_ID;
+ subsurface->falloff = CLOSURE_BSSRDF_BURLEY_ID;
break;
}
@@ -450,16 +425,16 @@ static ShaderNode *add_node(Scene *scene,
switch(b_glossy_node.distribution()) {
case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
- glossy->distribution = ustring("Sharp");
+ glossy->distribution = CLOSURE_BSDF_REFLECTION_ID;
break;
case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
- glossy->distribution = ustring("Beckmann");
+ glossy->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
break;
case BL::ShaderNodeBsdfGlossy::distribution_GGX:
- glossy->distribution = ustring("GGX");
+ glossy->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
break;
case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
- glossy->distribution = ustring("Ashikhmin-Shirley");
+ glossy->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
break;
}
node = glossy;
@@ -469,13 +444,13 @@ static ShaderNode *add_node(Scene *scene,
GlassBsdfNode *glass = new GlassBsdfNode();
switch(b_glass_node.distribution()) {
case BL::ShaderNodeBsdfGlass::distribution_SHARP:
- glass->distribution = ustring("Sharp");
+ glass->distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
break;
case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
- glass->distribution = ustring("Beckmann");
+ glass->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID;
break;
case BL::ShaderNodeBsdfGlass::distribution_GGX:
- glass->distribution = ustring("GGX");
+ glass->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
break;
}
node = glass;
@@ -485,13 +460,13 @@ static ShaderNode *add_node(Scene *scene,
RefractionBsdfNode *refraction = new RefractionBsdfNode();
switch(b_refraction_node.distribution()) {
case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
- refraction->distribution = ustring("Sharp");
+ refraction->distribution = CLOSURE_BSDF_REFRACTION_ID;
break;
case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
- refraction->distribution = ustring("Beckmann");
+ refraction->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
break;
case BL::ShaderNodeBsdfRefraction::distribution_GGX:
- refraction->distribution = ustring("GGX");
+ refraction->distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
break;
}
node = refraction;
@@ -501,10 +476,10 @@ static ShaderNode *add_node(Scene *scene,
ToonBsdfNode *toon = new ToonBsdfNode();
switch(b_toon_node.component()) {
case BL::ShaderNodeBsdfToon::component_DIFFUSE:
- toon->component = ustring("Diffuse");
+ toon->component = CLOSURE_BSDF_DIFFUSE_TOON_ID;
break;
case BL::ShaderNodeBsdfToon::component_GLOSSY:
- toon->component = ustring("Glossy");
+ toon->component = CLOSURE_BSDF_GLOSSY_TOON_ID;
break;
}
node = toon;
@@ -514,10 +489,10 @@ static ShaderNode *add_node(Scene *scene,
HairBsdfNode *hair = new HairBsdfNode();
switch(b_hair_node.component()) {
case BL::ShaderNodeBsdfHair::component_Reflection:
- hair->component = ustring("Reflection");
+ hair->component = CLOSURE_BSDF_HAIR_REFLECTION_ID;
break;
case BL::ShaderNodeBsdfHair::component_Transmission:
- hair->component = ustring("Transmission");
+ hair->component = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
break;
}
node = hair;
@@ -584,62 +559,17 @@ static ShaderNode *add_node(Scene *scene,
if(scene->shader_manager->use_osl()) {
/* create script node */
BL::ShaderNodeScript b_script_node(b_node);
- OSLScriptNode *script_node = new OSLScriptNode();
OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
string bytecode_hash = b_script_node.bytecode_hash();
- /* Gather additional information from the shader, such as
- * input/output type info needed for proper node construction.
- */
- OSL::OSLQuery query;
- string absolute_filepath;
-
- if(!bytecode_hash.empty()) {
- query.open_bytecode(b_script_node.bytecode());
- }
- else {
- absolute_filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
- OSLShaderManager::osl_query(query, absolute_filepath);
- }
- /* TODO(sergey): Add proper query info error parsing. */
-
- /* Generate inputs/outputs from node sockets
- *
- * Note: the node sockets are generated from OSL parameters,
- * so the names match those of the corresponding parameters exactly.
- *
- * Note 2: ShaderInput/ShaderOutput store shallow string copies only!
- * So we register them as ustring to ensure the pointer stays valid. */
- BL::Node::inputs_iterator b_input;
-
- for(b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) {
- ShaderInput *input = script_node->add_input(ustring(b_input->name()).c_str(),
- convert_osl_socket_type(query, *b_input));
- set_default_value(input, *b_input, b_data, b_ntree);
- }
-
- BL::Node::outputs_iterator b_output;
-
- for(b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) {
- script_node->add_output(ustring(b_output->name()).c_str(),
- convert_osl_socket_type(query, *b_output));
- }
-
- /* load bytecode or filepath */
if(!bytecode_hash.empty()) {
- /* loaded bytecode if not already done */
- if(!manager->shader_test_loaded(bytecode_hash))
- manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode());
-
- script_node->bytecode_hash = bytecode_hash;
+ node = manager->osl_node("", bytecode_hash, b_script_node.bytecode());
}
else {
- /* set filepath */
- script_node->filepath = absolute_filepath;
+ string absolute_filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
+ node = manager->osl_node(absolute_filepath, "");
}
-
- node = script_node;
}
#else
(void)b_data;
@@ -692,8 +622,8 @@ static ShaderNode *add_node(Scene *scene,
get_image_extension(b_image_node));
}
}
- image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
- image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
+ image->color_space = (NodeImageColorSpace)b_image_node.color_space();
+ image->projection = (NodeImageProjection)b_image_node.projection();
image->interpolation = get_image_interpolation(b_image_node);
image->extension = get_image_extension(b_image_node);
image->projection_blend = b_image_node.projection_blend();
@@ -738,9 +668,9 @@ static ShaderNode *add_node(Scene *scene,
EXTENSION_REPEAT);
}
}
- env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
+ env->color_space = (NodeImageColorSpace)b_env_node.color_space();
env->interpolation = get_image_interpolation(b_env_node);
- env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
+ env->projection = (NodeEnvironmentProjection)b_env_node.projection();
BL::TexMapping b_texture_mapping(b_env_node.texture_mapping());
get_tex_mapping(&env->tex_mapping, b_texture_mapping);
node = env;
@@ -748,7 +678,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexGradient)) {
BL::ShaderNodeTexGradient b_gradient_node(b_node);
GradientTextureNode *gradient = new GradientTextureNode();
- gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()];
+ gradient->type = (NodeGradientType)b_gradient_node.gradient_type();
BL::TexMapping b_texture_mapping(b_gradient_node.texture_mapping());
get_tex_mapping(&gradient->tex_mapping, b_texture_mapping);
node = gradient;
@@ -756,7 +686,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
VoronoiTextureNode *voronoi = new VoronoiTextureNode();
- voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()];
+ voronoi->coloring = (NodeVoronoiColoring)b_voronoi_node.coloring();
BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
node = voronoi;
@@ -772,8 +702,8 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexWave)) {
BL::ShaderNodeTexWave b_wave_node(b_node);
WaveTextureNode *wave = new WaveTextureNode();
- wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
- wave->profile = WaveTextureNode::profile_enum[(int)b_wave_node.wave_profile()];
+ wave->type = (NodeWaveType)b_wave_node.wave_type();
+ wave->profile = (NodeWaveProfile)b_wave_node.wave_profile();
BL::TexMapping b_texture_mapping(b_wave_node.texture_mapping());
get_tex_mapping(&wave->tex_mapping, b_texture_mapping);
node = wave;
@@ -806,7 +736,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
MusgraveTextureNode *musgrave = new MusgraveTextureNode();
- musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()];
+ musgrave->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
get_tex_mapping(&musgrave->tex_mapping, b_texture_mapping);
node = musgrave;
@@ -824,7 +754,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexSky)) {
BL::ShaderNodeTexSky b_sky_node(b_node);
SkyTextureNode *sky = new SkyTextureNode();
- sky->type = SkyTextureNode::type_enum[(int)b_sky_node.sky_type()];
+ sky->type = (NodeSkyType)b_sky_node.sky_type();
sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction()));
sky->turbidity = b_sky_node.turbidity();
sky->ground_albedo = b_sky_node.ground_albedo();
@@ -835,15 +765,15 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) {
BL::ShaderNodeNormalMap b_normal_map_node(b_node);
NormalMapNode *nmap = new NormalMapNode();
- nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()];
+ nmap->space = (NodeNormalMapSpace)b_normal_map_node.space();
nmap->attribute = b_normal_map_node.uv_map();
node = nmap;
}
else if(b_node.is_a(&RNA_ShaderNodeTangent)) {
BL::ShaderNodeTangent b_tangent_node(b_node);
TangentNode *tangent = new TangentNode();
- tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
- tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
+ tangent->direction_type = (NodeTangentDirectionType)b_tangent_node.direction_type();
+ tangent->axis = (NodeTangentAxis)b_tangent_node.axis();
tangent->attribute = b_tangent_node.uv_map();
node = tangent;
}
@@ -858,8 +788,7 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
PointDensityTextureNode *point_density = new PointDensityTextureNode();
point_density->filename = b_point_density_node.name();
- point_density->space =
- PointDensityTextureNode::space_enum[(int)b_point_density_node.space()];
+ point_density->space = (NodeTexVoxelSpace)b_point_density_node.space();
point_density->interpolation = get_image_interpolation(b_point_density_node);
point_density->builtin_data = b_point_density_node.ptr.data;
@@ -1020,7 +949,7 @@ static void add_nodes(Scene *scene,
BL::Node::internal_links_iterator b_link;
for(b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) {
BL::NodeSocket to_socket(b_link->to_socket());
- ShaderSocketType to_socket_type = convert_socket_type(to_socket);
+ SocketType::Type to_socket_type = convert_socket_type(to_socket);
ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true);
input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
@@ -1043,7 +972,7 @@ static void add_nodes(Scene *scene,
* so that links have something to connect to and assert won't fail.
*/
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
- ShaderSocketType input_type = convert_socket_type(*b_input);
+ SocketType::Type input_type = convert_socket_type(*b_input);
ConvertNode *proxy = new ConvertNode(input_type, input_type, true);
graph->add(proxy);
@@ -1055,7 +984,7 @@ static void add_nodes(Scene *scene,
set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree);
}
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
- ShaderSocketType output_type = convert_socket_type(*b_output);
+ SocketType::Type output_type = convert_socket_type(*b_output);
ConvertNode *proxy = new ConvertNode(output_type, output_type, true);
graph->add(proxy);
@@ -1227,7 +1156,7 @@ void BlenderSync::sync_materials(bool update_all)
ShaderNode *closure, *out;
closure = graph->add(new DiffuseBsdfNode());
- closure->input("Color")->value = get_float3(b_mat->diffuse_color());
+ closure->input("Color")->set(get_float3(b_mat->diffuse_color()));
out = graph->output();
graph->connect(closure->output("BSDF"), out->input("Surface"));
@@ -1276,7 +1205,7 @@ void BlenderSync::sync_world(bool update_all)
ShaderNode *closure, *out;
closure = graph->add(new BackgroundNode());
- closure->input("Color")->value = get_float3(b_world.horizon_color());
+ closure->input("Color")->set(get_float3(b_world.horizon_color()));
out = graph->output();
graph->connect(closure->output("Background"), out->input("Surface"));
@@ -1369,8 +1298,8 @@ void BlenderSync::sync_lamps(bool update_all)
}
closure = graph->add(new EmissionNode());
- closure->input("Color")->value = get_float3(b_lamp->color());
- closure->input("Strength")->value.x = strength;
+ closure->input("Color")->set(get_float3(b_lamp->color()));
+ closure->input("Strength")->set(strength);
out = graph->output();
graph->connect(closure->output("Emission"), out->input("Surface"));
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 3e8856c8de6..89a53a1deca 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -98,11 +98,12 @@ static inline void curvemapping_minmax(/*const*/ BL::CurveMapping& cumap,
}
static inline void curvemapping_to_array(BL::CurveMapping& cumap,
- float *data,
+ array<float>& data,
int size)
{
cumap.update();
BL::CurveMap curve = cumap.curves[0];
+ data.resize(size);
for(int i = 0; i < size; i++) {
float t = (float)i/(float)(size-1);
data[i] = curve.evaluate(t);
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 5c474c8c3e9..fa2b9ae7279 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -128,11 +128,11 @@ void BVH::pack_triangle(int idx, float4 storage[3])
const Mesh *mesh = objects[tob]->mesh;
int tidx = pack.prim_index[idx];
- const int *vidx = mesh->triangles[tidx].v;
+ Mesh::Triangle t = mesh->get_triangle(tidx);
const float3* vpos = &mesh->verts[0];
- float3 v0 = vpos[vidx[0]];
- float3 v1 = vpos[vidx[1]];
- float3 v2 = vpos[vidx[2]];
+ float3 v0 = vpos[t.v[0]];
+ float3 v1 = vpos[t.v[1]];
+ float3 v2 = vpos[t.v[2]];
storage[0] = float3_to_float4(v0);
storage[1] = float3_to_float4(v1);
@@ -506,10 +506,10 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
/* curves */
int str_offset = (params.top_level)? mesh->curve_offset: 0;
- const Mesh::Curve& curve = mesh->curves[pidx - str_offset];
+ Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
- curve.bounds_grow(k, &mesh->curve_keys[0], bbox);
+ curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);
visibility |= PATH_RAY_CURVE;
@@ -520,17 +520,17 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
if(attr) {
size_t mesh_size = mesh->curve_keys.size();
size_t steps = mesh->motion_steps - 1;
- float4 *key_steps = attr->data_float4();
+ float3 *key_steps = attr->data_float3();
for(size_t i = 0; i < steps; i++)
- curve.bounds_grow(k, key_steps + i*mesh_size, bbox);
+ curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox);
}
}
}
else {
/* triangles */
int tri_offset = (params.top_level)? mesh->tri_offset: 0;
- const Mesh::Triangle& triangle = mesh->triangles[pidx - tri_offset];
+ Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
const float3 *vpos = &mesh->verts[0];
triangle.bounds_grow(vpos, bbox);
@@ -770,10 +770,10 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
/* Curves. */
int str_offset = (params.top_level)? mesh->curve_offset: 0;
- const Mesh::Curve& curve = mesh->curves[pidx - str_offset];
+ Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);
- curve.bounds_grow(k, &mesh->curve_keys[0], bbox);
+ curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);
visibility |= PATH_RAY_CURVE;
@@ -784,17 +784,17 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
if(attr) {
size_t mesh_size = mesh->curve_keys.size();
size_t steps = mesh->motion_steps - 1;
- float4 *key_steps = attr->data_float4();
+ float3 *key_steps = attr->data_float3();
for(size_t i = 0; i < steps; i++)
- curve.bounds_grow(k, key_steps + i*mesh_size, bbox);
+ curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox);
}
}
}
else {
/* Triangles. */
int tri_offset = (params.top_level)? mesh->tri_offset: 0;
- const Mesh::Triangle& triangle = mesh->triangles[pidx - tri_offset];
+ Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
const float3 *vpos = &mesh->verts[0];
triangle.bounds_grow(vpos, bbox);
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 76a1bfa2bfe..87a889955fe 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -117,8 +117,9 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
if(mesh->has_motion_blur())
attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- for(uint j = 0; j < mesh->triangles.size(); j++) {
- Mesh::Triangle t = mesh->triangles[j];
+ size_t num_triangles = mesh->num_triangles();
+ for(uint j = 0; j < num_triangles; j++) {
+ Mesh::Triangle t = mesh->get_triangle(j);
BoundBox bounds = BoundBox::empty;
PrimitiveType type = PRIMITIVE_TRIANGLE;
@@ -148,22 +149,23 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
if(mesh->has_motion_blur())
curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- for(uint j = 0; j < mesh->curves.size(); j++) {
- Mesh::Curve curve = mesh->curves[j];
+ size_t num_curves = mesh->num_curves();
+ for(uint j = 0; j < num_curves; j++) {
+ Mesh::Curve curve = mesh->get_curve(j);
PrimitiveType type = PRIMITIVE_CURVE;
for(int k = 0; k < curve.num_keys - 1; k++) {
BoundBox bounds = BoundBox::empty;
- curve.bounds_grow(k, &mesh->curve_keys[0], bounds);
+ curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bounds);
/* motion curve */
if(curve_attr_mP) {
size_t mesh_size = mesh->curve_keys.size();
size_t steps = mesh->motion_steps - 1;
- float4 *key_steps = curve_attr_mP->data_float4();
+ float3 *key_steps = curve_attr_mP->data_float3();
for(size_t i = 0; i < steps; i++)
- curve.bounds_grow(k, key_steps + i*mesh_size, bounds);
+ curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bounds);
type = PRIMITIVE_MOTION_CURVE;
}
@@ -188,10 +190,10 @@ void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob
static size_t count_curve_segments(Mesh *mesh)
{
- size_t num = 0, num_curves = mesh->curves.size();
+ size_t num = 0, num_curves = mesh->num_curves();
for(size_t i = 0; i < num_curves; i++)
- num += mesh->curves[i].num_keys - 1;
+ num += mesh->get_curve(i).num_keys - 1;
return num;
}
@@ -204,14 +206,14 @@ void BVHBuild::add_references(BVHRange& root)
foreach(Object *ob, objects) {
if(params.top_level) {
if(!ob->mesh->is_instanced()) {
- num_alloc_references += ob->mesh->triangles.size();
+ num_alloc_references += ob->mesh->num_triangles();
num_alloc_references += count_curve_segments(ob->mesh);
}
else
num_alloc_references++;
}
else {
- num_alloc_references += ob->mesh->triangles.size();
+ num_alloc_references += ob->mesh->num_triangles();
num_alloc_references += count_curve_segments(ob->mesh);
}
}
@@ -326,11 +328,11 @@ BVHNode* BVHBuild::run()
VLOG(1) << "BVH build statistics:\n"
<< " Build time: " << time_dt() - build_start_time << "\n"
<< " Total number of nodes: "
- << rootnode->getSubtreeSize(BVH_STAT_NODE_COUNT) << "\n"
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_NODE_COUNT)) << "\n"
<< " Number of inner nodes: "
- << rootnode->getSubtreeSize(BVH_STAT_INNER_COUNT) << "\n"
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_INNER_COUNT)) << "\n"
<< " Number of leaf nodes: "
- << rootnode->getSubtreeSize(BVH_STAT_LEAF_COUNT) << "\n"
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_LEAF_COUNT)) << "\n"
<< " Allocation slop factor: "
<< ((prim_type.capacity() != 0)
? (float)prim_type.size() / prim_type.capacity()
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index 8084975565e..3665fb42bc2 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -292,13 +292,13 @@ void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh,
BoundBox& left_bounds,
BoundBox& right_bounds)
{
- const int *inds = mesh->triangles[prim_index].v;
+ Mesh::Triangle t = mesh->get_triangle(prim_index);
const float3 *verts = &mesh->verts[0];
- float3 v1 = tfm ? transform_point(tfm, verts[inds[2]]) : verts[inds[2]];
+ float3 v1 = tfm ? transform_point(tfm, verts[t.v[2]]) : verts[t.v[2]];
for(int i = 0; i < 3; i++) {
float3 v0 = v1;
- int vindex = inds[i];
+ int vindex = t.v[i];
v1 = tfm ? transform_point(tfm, verts[vindex]) : verts[vindex];
float v0p = v0[dim];
float v1p = v1[dim];
@@ -329,12 +329,11 @@ void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh,
BoundBox& right_bounds)
{
/* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
- const int k0 = mesh->curves[prim_index].first_key + segment_index;
+ Mesh::Curve curve = mesh->get_curve(prim_index);
+ const int k0 = curve.first_key + segment_index;
const int k1 = k0 + 1;
- const float4& key0 = mesh->curve_keys[k0];
- const float4& key1 = mesh->curve_keys[k1];
- float3 v0 = float4_to_float3(key0);
- float3 v1 = float4_to_float3(key1);
+ float3 v0 = mesh->curve_keys[k0];
+ float3 v1 = mesh->curve_keys[k1];
if(tfm != NULL) {
v0 = transform_point(tfm, v0);
@@ -414,8 +413,8 @@ void BVHSpatialSplit::split_object_reference(const Object *object,
left_bounds,
right_bounds);
}
- for(int curve_idx = 0; curve_idx < mesh->curves.size(); ++curve_idx) {
- Mesh::Curve &curve = mesh->curves[curve_idx];
+ for(int curve_idx = 0; curve_idx < mesh->num_curves(); ++curve_idx) {
+ Mesh::Curve curve = mesh->get_curve(curve_idx);
for(int segment_idx = 0;
segment_idx < curve.num_keys - 1;
++segment_idx)
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 275ee028eb4..aed86d8d853 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -155,7 +155,9 @@ public:
InterpolationType interpolation,
ExtensionType extension)
{
- VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ VLOG(1) << "Texture allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
kernel_tex_copy(&kernel_globals,
name,
mem.data_pointer,
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 9a78d055580..d7ed7b4f853 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -493,7 +493,9 @@ public:
InterpolationType interpolation,
ExtensionType extension)
{
- VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ VLOG(1) << "Texture allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
/* Check if we are on sm_30 or above.
* We use arrays and bindles textures for storage there */
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index 434d0085d39..c4f8d9e16e0 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -175,7 +175,9 @@ public:
interpolation,
ExtensionType extension)
{
- VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ VLOG(1) << "Texture allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
foreach(SubDevice& sub, devices) {
mem.device_pointer = 0;
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index cf4a05de8fc..3eb5ad2d2db 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -168,7 +168,9 @@ public:
InterpolationType interpolation,
ExtensionType extension)
{
- VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ VLOG(1) << "Texture allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
thread_scoped_lock lock(rpc_lock);
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 1b4e5421b5a..afe21c49730 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -1187,7 +1187,9 @@ public:
InterpolationType /*interpolation*/,
ExtensionType /*extension*/)
{
- VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ VLOG(1) << "Texture allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
mem_alloc(mem, MEM_READ_ONLY);
mem_copy_to(mem);
assert(mem_map.find(name) == mem_map.end());
@@ -1222,18 +1224,28 @@ public:
CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &workgroup_size, NULL);
clGetDeviceInfo(cdDevice,
CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t)*3, max_work_items, NULL);
-
- /* try to divide evenly over 2 dimensions */
+
+ /* Try to divide evenly over 2 dimensions. */
size_t sqrt_workgroup_size = max((size_t)sqrt((double)workgroup_size), 1);
size_t local_size[2] = {sqrt_workgroup_size, sqrt_workgroup_size};
- /* some implementations have max size 1 on 2nd dimension */
+ /* Some implementations have max size 1 on 2nd dimension. */
if(local_size[1] > max_work_items[1]) {
local_size[0] = workgroup_size/max_work_items[1];
local_size[1] = max_work_items[1];
}
- size_t global_size[2] = {global_size_round_up(local_size[0], w), global_size_round_up(local_size[1], h)};
+ size_t global_size[2] = {global_size_round_up(local_size[0], w),
+ global_size_round_up(local_size[1], h)};
+
+ /* Vertical size of 1 is coming from bake/shade kernels where we should
+ * not round anything up because otherwise we'll either be doing too
+ * much work per pixel (if we don't check global ID on Y axis) or will
+ * be checking for global ID to always have Y of 0.
+ */
+ if (h == 1) {
+ global_size[h] = 1;
+ }
/* run kernel */
opencl_assert(clEnqueueNDRangeKernel(cqCommandQueue, kernel, 2, NULL, global_size, NULL, 0, NULL, NULL));
@@ -1318,48 +1330,49 @@ public:
else
kernel = ckShaderKernel;
- for(int sample = 0; sample < task.num_samples; sample++) {
-
- if(task.get_cancel())
- break;
-
- cl_int d_sample = sample;
-
- cl_uint start_arg_index =
- kernel_set_args(kernel,
- 0,
- d_data,
- d_input,
- d_output);
+ cl_uint start_arg_index =
+ kernel_set_args(kernel,
+ 0,
+ d_data,
+ d_input,
+ d_output);
- if(task.shader_eval_type < SHADER_EVAL_BAKE) {
- start_arg_index += kernel_set_args(kernel,
- start_arg_index,
- d_output_luma);
- }
+ if(task.shader_eval_type < SHADER_EVAL_BAKE) {
+ start_arg_index += kernel_set_args(kernel,
+ start_arg_index,
+ d_output_luma);
+ }
#define KERNEL_TEX(type, ttype, name) \
- set_kernel_arg_mem(kernel, &start_arg_index, #name);
+ set_kernel_arg_mem(kernel, &start_arg_index, #name);
#include "kernel_textures.h"
#undef KERNEL_TEX
+ start_arg_index += kernel_set_args(kernel,
+ start_arg_index,
+ d_shader_eval_type);
+ if(task.shader_eval_type >= SHADER_EVAL_BAKE) {
start_arg_index += kernel_set_args(kernel,
start_arg_index,
- d_shader_eval_type);
- if(task.shader_eval_type >= SHADER_EVAL_BAKE) {
- start_arg_index += kernel_set_args(kernel,
- start_arg_index,
- d_shader_filter);
- }
- start_arg_index += kernel_set_args(kernel,
- start_arg_index,
- d_shader_x,
- d_shader_w,
- d_offset,
- d_sample);
+ d_shader_filter);
+ }
+ start_arg_index += kernel_set_args(kernel,
+ start_arg_index,
+ d_shader_x,
+ d_shader_w,
+ d_offset);
+
+ for(int sample = 0; sample < task.num_samples; sample++) {
+
+ if(task.get_cancel())
+ break;
+
+ kernel_set_args(kernel, start_arg_index, sample);
enqueue_kernel(kernel, task.shader_w, 1);
+ clFinish(cqCommandQueue);
+
task.update_progress(NULL);
}
}
diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp
index d482577b73b..941a66741c5 100644
--- a/intern/cycles/graph/node.cpp
+++ b/intern/cycles/graph/node.cpp
@@ -36,12 +36,8 @@ Node::Node(const NodeType *type_, ustring name_)
}
/* initialize default values */
- typedef unordered_map<ustring, SocketType, ustringHash> map_type;
- foreach(const map_type::value_type& it, type->inputs) {
- const SocketType& socket = it.second;
- const void *src = socket.default_value;
- void *dst = ((char*)this) + socket.struct_offset;
- memcpy(dst, src, socket.size());
+ foreach(const SocketType& socket, type->inputs) {
+ set_default_value(socket);
}
}
@@ -104,6 +100,11 @@ void Node::set(const SocketType& input, float3 value)
get_socket_value<float3>(this, input) = value;
}
+void Node::set(const SocketType& input, const char *value)
+{
+ set(input, ustring(value));
+}
+
void Node::set(const SocketType& input, ustring value)
{
if(input.type == SocketType::STRING) {
@@ -292,7 +293,8 @@ const array<Node*>& Node::get_node_array(const SocketType& input) const
return get_socket_value<array<Node*> >(this, input);
}
-/* default values */
+/* generic value operations */
+
bool Node::has_default_value(const SocketType& input) const
{
const void *src = input.default_value;
@@ -300,6 +302,48 @@ bool Node::has_default_value(const SocketType& input) const
return memcmp(dst, src, input.size()) == 0;
}
+void Node::set_default_value(const SocketType& socket)
+{
+ const void *src = socket.default_value;
+ void *dst = ((char*)this) + socket.struct_offset;
+ memcpy(dst, src, socket.size());
+}
+
+template<typename T>
+static void copy_array(const Node *node, const SocketType& socket, const Node *other, const SocketType& other_socket)
+{
+ const array<T>* src = (const array<T>*)(((char*)other) + other_socket.struct_offset);
+ array<T>* dst = (array<T>*)(((char*)node) + socket.struct_offset);
+ *dst = *src;
+}
+
+void Node::copy_value(const SocketType& socket, const Node& other, const SocketType& other_socket)
+{
+ assert(socket.type == other_socket.type);
+
+ if(socket.is_array()) {
+ switch(socket.type) {
+ case SocketType::BOOLEAN_ARRAY: copy_array<bool>(this, socket, &other, other_socket); break;
+ case SocketType::FLOAT_ARRAY: copy_array<float>(this, socket, &other, other_socket); break;
+ case SocketType::INT_ARRAY: copy_array<int>(this, socket, &other, other_socket); break;
+ case SocketType::COLOR_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
+ case SocketType::VECTOR_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
+ case SocketType::POINT_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
+ case SocketType::NORMAL_ARRAY: copy_array<float3>(this, socket, &other, other_socket); break;
+ case SocketType::POINT2_ARRAY: copy_array<float2>(this, socket, &other, other_socket); break;
+ case SocketType::STRING_ARRAY: copy_array<ustring>(this, socket, &other, other_socket); break;
+ case SocketType::TRANSFORM_ARRAY: copy_array<Transform>(this, socket, &other, other_socket); break;
+ case SocketType::NODE_ARRAY: copy_array<void*>(this, socket, &other, other_socket); break;
+ default: assert(0); break;
+ }
+ }
+ else {
+ const void *src = ((char*)&other) + other_socket.struct_offset;
+ void *dst = ((char*)this) + socket.struct_offset;
+ memcpy(dst, src, socket.size());
+ }
+}
+
template<typename T>
static bool is_array_equal(const Node *node, const Node *other, const SocketType& socket)
{
@@ -308,48 +352,43 @@ static bool is_array_equal(const Node *node, const Node *other, const SocketType
return *a == *b;
}
-/* modified */
-bool Node::modified(const Node& other)
+bool Node::equals_value(const Node& other, const SocketType& socket) const
+{
+ if(socket.is_array()) {
+ switch(socket.type) {
+ case SocketType::BOOLEAN_ARRAY: return is_array_equal<bool>(this, &other, socket);
+ case SocketType::FLOAT_ARRAY: return is_array_equal<float>(this, &other, socket);
+ case SocketType::INT_ARRAY: return is_array_equal<int>(this, &other, socket);
+ case SocketType::COLOR_ARRAY: return is_array_equal<float3>(this, &other, socket);
+ case SocketType::VECTOR_ARRAY: return is_array_equal<float3>(this, &other, socket);
+ case SocketType::POINT_ARRAY: return is_array_equal<float3>(this, &other, socket);
+ case SocketType::NORMAL_ARRAY: return is_array_equal<float3>(this, &other, socket);
+ case SocketType::POINT2_ARRAY: return is_array_equal<float2>(this, &other, socket);
+ case SocketType::STRING_ARRAY: return is_array_equal<ustring>(this, &other, socket);
+ case SocketType::TRANSFORM_ARRAY: return is_array_equal<Transform>(this, &other, socket);
+ case SocketType::NODE_ARRAY: return is_array_equal<void*>(this, &other, socket);
+ default: assert(0); return true;
+ }
+ }
+ else {
+ const void *a = ((char*)this) + socket.struct_offset;
+ const void *b = ((char*)&other) + socket.struct_offset;
+ return (memcmp(a, b, socket.size()) == 0);
+ }
+}
+
+/* equals */
+
+bool Node::equals(const Node& other) const
{
assert(type == other.type);
- typedef unordered_map<ustring, SocketType, ustringHash> map_type;
- foreach(const map_type::value_type& it, type->inputs) {
- const SocketType& socket = it.second;
-
- if(socket.is_array()) {
- bool equal = true;
-
- switch(socket.type)
- {
- case SocketType::BOOLEAN_ARRAY: equal = is_array_equal<bool>(this, &other, socket); break;
- case SocketType::FLOAT_ARRAY: equal = is_array_equal<float>(this, &other, socket); break;
- case SocketType::INT_ARRAY: equal = is_array_equal<int>(this, &other, socket); break;
- case SocketType::COLOR_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
- case SocketType::VECTOR_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
- case SocketType::POINT_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
- case SocketType::NORMAL_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
- case SocketType::POINT2_ARRAY: equal = is_array_equal<float2>(this, &other, socket); break;
- case SocketType::STRING_ARRAY: equal = is_array_equal<ustring>(this, &other, socket); break;
- case SocketType::TRANSFORM_ARRAY: equal = is_array_equal<Transform>(this, &other, socket); break;
- case SocketType::NODE_ARRAY: equal = is_array_equal<void*>(this, &other, socket); break;
- default: assert(0); break;
- }
-
- if(!equal) {
- return true;
- }
- }
- else {
- const void *a = ((char*)this) + socket.struct_offset;
- const void *b = ((char*)&other) + socket.struct_offset;
- if(memcmp(a, b, socket.size()) != 0) {
- return true;
- }
- }
+ foreach(const SocketType& socket, type->inputs) {
+ if(!equals_value(other, socket))
+ return false;
}
- return false;
+ return true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h
index 33971fa714a..bb84f982fb3 100644
--- a/intern/cycles/graph/node.h
+++ b/intern/cycles/graph/node.h
@@ -41,6 +41,7 @@ struct Node
void set(const SocketType& input, float value);
void set(const SocketType& input, float2 value);
void set(const SocketType& input, float3 value);
+ void set(const SocketType& input, const char *value);
void set(const SocketType& input, ustring value);
void set(const SocketType& input, const Transform& value);
void set(const SocketType& input, Node *value);
@@ -76,11 +77,14 @@ struct Node
const array<Transform>& get_transform_array(const SocketType& input) const;
const array<Node*>& get_node_array(const SocketType& input) const;
- /* default values */
+ /* generic values operations */
bool has_default_value(const SocketType& input) const;
+ void set_default_value(const SocketType& input);
+ bool equals_value(const Node& other, const SocketType& input) const;
+ void copy_value(const SocketType& input, const Node& other, const SocketType& other_input);
- /* modified */
- bool modified(const Node& other);
+ /* equals */
+ bool equals(const Node& other) const;
ustring name;
const NodeType *type;
diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp
index dc879655d7f..7f68ae9c7c7 100644
--- a/intern/cycles/graph/node_type.cpp
+++ b/intern/cycles/graph/node_type.cpp
@@ -114,9 +114,15 @@ ustring SocketType::type_name(Type type)
return names[(int)type];
}
+bool SocketType::is_float3(Type type)
+{
+ return (type == COLOR || type == VECTOR || type == POINT || type == NORMAL);
+}
+
/* Node Type */
-NodeType::NodeType()
+NodeType::NodeType(Type type_)
+: type(type_)
{
}
@@ -137,7 +143,7 @@ void NodeType::register_input(ustring name, ustring ui_name, SocketType::Type ty
socket.enum_values = enum_values;
socket.node_type = node_type;
socket.flags = flags | extra_flags;
- inputs[name] = socket;
+ inputs.push_back(socket);
}
void NodeType::register_output(ustring name, ustring ui_name, SocketType::Type type)
@@ -151,7 +157,29 @@ void NodeType::register_output(ustring name, ustring ui_name, SocketType::Type t
socket.enum_values = NULL;
socket.node_type = NULL;
socket.flags = SocketType::LINKABLE;
- outputs[name] = socket;
+ outputs.push_back(socket);
+}
+
+const SocketType *NodeType::find_input(ustring name) const
+{
+ foreach(const SocketType& socket, inputs) {
+ if(socket.name == name) {
+ return &socket;
+ }
+ }
+
+ return NULL;
+}
+
+const SocketType *NodeType::find_output(ustring name) const
+{
+ foreach(const SocketType& socket, outputs) {
+ if(socket.name == name) {
+ return &socket;
+ }
+ }
+
+ return NULL;
}
/* Node Type Registry */
@@ -162,7 +190,7 @@ unordered_map<ustring, NodeType, ustringHash>& NodeType::types()
return _types;
}
-NodeType *NodeType::add(const char *name_, CreateFunc create_)
+NodeType *NodeType::add(const char *name_, CreateFunc create_, Type type_)
{
ustring name(name_);
@@ -172,7 +200,7 @@ NodeType *NodeType::add(const char *name_, CreateFunc create_)
return NULL;
}
- types()[name] = NodeType();
+ types()[name] = NodeType(type_);
NodeType *type = &types()[name];
type->name = name;
diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h
index 82ddd29da33..20816f634cd 100644
--- a/intern/cycles/graph/node_type.h
+++ b/intern/cycles/graph/node_type.h
@@ -21,6 +21,7 @@
#include "util_map.h"
#include "util_param.h"
#include "util_string.h"
+#include "util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -94,13 +95,19 @@ struct SocketType
static size_t max_size();
static ustring type_name(Type type);
static void *zero_default_value();
+ static bool is_float3(Type type);
};
/* Node Type */
struct NodeType
{
- explicit NodeType();
+ enum Type {
+ NONE,
+ SHADER
+ };
+
+ explicit NodeType(Type type = NONE);
~NodeType();
void register_input(ustring name, ustring ui_name, SocketType::Type type,
@@ -110,15 +117,18 @@ struct NodeType
int flags = 0, int extra_flags = 0);
void register_output(ustring name, ustring ui_name, SocketType::Type type);
+ const SocketType *find_input(ustring name) const;
+ const SocketType *find_output(ustring name) const;
+
typedef Node *(*CreateFunc)(const NodeType *type);
- typedef unordered_map<ustring, SocketType, ustringHash> SocketMap;
ustring name;
- SocketMap inputs;
- SocketMap outputs;
+ Type type;
+ std::vector<SocketType> inputs;
+ std::vector<SocketType> outputs;
CreateFunc create;
- static NodeType *add(const char *name, CreateFunc create);
+ static NodeType *add(const char *name, CreateFunc create, Type type = NONE);
static const NodeType *find(ustring name);
static unordered_map<ustring, NodeType, ustringHash>& types();
};
diff --git a/intern/cycles/graph/node_xml.cpp b/intern/cycles/graph/node_xml.cpp
index fe06a243998..022de7cf32a 100644
--- a/intern/cycles/graph/node_xml.cpp
+++ b/intern/cycles/graph/node_xml.cpp
@@ -58,9 +58,7 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
node->name = ustring(name_attr.value());
}
- foreach(const NodeType::SocketMap::value_type& it, node->type->inputs) {
- const SocketType& socket = it.second;
-
+ foreach(const SocketType& socket, node->type->inputs) {
if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
continue;
}
@@ -117,8 +115,9 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
array<int> value;
value.resize(tokens.size());
- for(size_t i = 0; i < value.size(); i++)
+ for(size_t i = 0; i < value.size(); i++) {
value[i] = (int)atoi(attr.value());
+ }
node->set(socket, value);
break;
}
@@ -127,7 +126,7 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
case SocketType::POINT:
case SocketType::NORMAL:
{
- array<float> value;
+ array<float3> value;
xml_read_float_array<3>(value, attr);
if(value.size() == 1) {
node->set(socket, value[0]);
@@ -161,11 +160,21 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
break;
}
case SocketType::STRING:
- case SocketType::ENUM:
{
node->set(socket, attr.value());
break;
}
+ case SocketType::ENUM:
+ {
+ ustring value(attr.value());
+ if(socket.enum_values->exists(value)) {
+ node->set(socket, value);
+ }
+ else {
+ fprintf(stderr, "Unknown value \"%s\" for attribute \"%s\".\n", value.c_str(), socket.name.c_str());
+ }
+ break;
+ }
case SocketType::STRING_ARRAY:
{
vector<string> tokens;
@@ -173,8 +182,9 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
array<ustring> value;
value.resize(tokens.size());
- for(size_t i = 0; i < value.size(); i++)
+ for(size_t i = 0; i < value.size(); i++) {
value[i] = ustring(tokens[i]);
+ }
node->set(socket, value);
break;
}
@@ -245,9 +255,7 @@ pugi::xml_node xml_write_node(Node *node, pugi::xml_node xml_root)
xml_node.append_attribute("name") = node->name.c_str();
- foreach(const NodeType::SocketMap::value_type& it, node->type->inputs) {
- const SocketType& socket = it.second;
-
+ foreach(const SocketType& socket, node->type->inputs) {
if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
continue;
}
diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/geom/geom_bvh.h
index 9eadc97386c..d0eedd3396a 100644
--- a/intern/cycles/kernel/geom/geom_bvh.h
+++ b/intern/cycles/kernel/geom/geom_bvh.h
@@ -48,6 +48,28 @@ CCL_NAMESPACE_BEGIN
#define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
+/* Debugging heleprs */
+#ifdef __KERNEL_DEBUG__
+# define BVH_DEBUG_INIT() \
+ do { \
+ isect->num_traversal_steps = 0; \
+ isect->num_traversed_instances = 0; \
+ } while(0)
+# define BVH_DEBUG_NEXT_STEP() \
+ do { \
+ ++isect->num_traversal_steps; \
+ } while(0)
+# define BVH_DEBUG_NEXT_INSTANCE() \
+ do { \
+ ++isect->num_traversed_instances; \
+ } while(0)
+#else /* __KERNEL_DEBUG__ */
+# define BVH_DEBUG_INIT()
+# define BVH_DEBUG_NEXT_STEP()
+# define BVH_DEBUG_NEXT_INSTANCE()
+#endif /* __KERNEL_DEBUG__ */
+
+
/* Common QBVH functions. */
#ifdef __QBVH__
# include "geom_qbvh.h"
diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h
index 8560612addc..ae919ef3f86 100644
--- a/intern/cycles/kernel/geom/geom_bvh_traversal.h
+++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h
@@ -74,10 +74,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
isect->prim = PRIM_NONE;
isect->object = OBJECT_NONE;
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps = 0;
- isect->num_traversed_instances = 0;
-#endif
+ BVH_DEBUG_INIT();
#if defined(__KERNEL_SSE2__)
const shuffle_swap_t shuf_identity = shuffle_swap_identity();
@@ -241,10 +238,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
--stackPtr;
}
}
-
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-#endif
+ BVH_DEBUG_NEXT_STEP();
}
/* if node is leaf, fetch triangle list */
@@ -266,9 +260,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
for(; primAddr < primAddr2; primAddr++) {
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-#endif
+ BVH_DEBUG_NEXT_STEP();
kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
if(triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr)) {
/* shadow ray early termination */
@@ -287,9 +279,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
for(; primAddr < primAddr2; primAddr++) {
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-# endif
+ BVH_DEBUG_NEXT_STEP();
kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
/* shadow ray early termination */
@@ -310,9 +300,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
case PRIMITIVE_CURVE:
case PRIMITIVE_MOTION_CURVE: {
for(; primAddr < primAddr2; primAddr++) {
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-# endif
+ BVH_DEBUG_NEXT_STEP();
kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
bool hit;
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
@@ -364,9 +352,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
nodeAddr = kernel_tex_fetch(__object_node, object);
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversed_instances++;
-# endif
+ BVH_DEBUG_NEXT_INSTANCE();
}
}
#endif /* FEATURE(BVH_INSTANCING) */
diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
index ce3bbbdf957..738d08ac6fc 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_traversal.h
+++ b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
@@ -78,10 +78,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
isect->prim = PRIM_NONE;
isect->object = OBJECT_NONE;
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps = 0;
- isect->num_traversed_instances = 0;
-#endif
+ BVH_DEBUG_INIT();
ssef tnear(0.0f), tfar(ray->t);
sse3f idir4(ssef(idir.x), ssef(idir.y), ssef(idir.z));
@@ -120,9 +117,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
int traverseChild;
ssef dist;
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-#endif
+ BVH_DEBUG_NEXT_STEP();
#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
if(difl != 0.0f) {
@@ -295,9 +290,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
for(; primAddr < primAddr2; primAddr++) {
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-#endif
+ BVH_DEBUG_NEXT_STEP();
kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
if(triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr)) {
tfar = ssef(isect->t);
@@ -311,9 +304,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
for(; primAddr < primAddr2; primAddr++) {
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-# endif
+ BVH_DEBUG_NEXT_STEP();
kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
tfar = ssef(isect->t);
@@ -329,9 +320,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
case PRIMITIVE_CURVE:
case PRIMITIVE_MOTION_CURVE: {
for(; primAddr < primAddr2; primAddr++) {
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-# endif
+ BVH_DEBUG_NEXT_STEP();
kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
bool hit;
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
@@ -381,9 +370,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
nodeAddr = kernel_tex_fetch(__object_node, object);
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversed_instances++;
-# endif
+ BVH_DEBUG_NEXT_INSTANCE();
}
}
#endif /* FEATURE(BVH_INSTANCING) */
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index 77982ee548a..8d05befe1d4 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -30,8 +30,8 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
Ray ray;
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- /* emission shader data memory used by various functions */
- ShaderData emission_sd;
+ /* emission and indirect shader data memory used by various functions */
+ ShaderData emission_sd, indirect_sd;
ray.P = sd->P + sd->Ng;
ray.D = -sd->Ng;
@@ -94,6 +94,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
&L_sample,
&throughput);
kernel_path_indirect(kg,
+ &indirect_sd,
&emission_sd,
&rng,
&ray,
@@ -117,7 +118,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
state.ray_t = 0.0f;
#endif
/* compute indirect light */
- kernel_path_indirect(kg, &emission_sd, &rng, &ray, throughput, 1, &state, &L_sample);
+ kernel_path_indirect(kg, &indirect_sd, &emission_sd, &rng, &ray, throughput, 1, &state, &L_sample);
/* sum and reset indirect light pass variables for the next samples */
path_radiance_sum_indirect(&L_sample);
@@ -144,7 +145,8 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
/* sample subsurface scattering */
if((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) {
/* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
- kernel_branched_path_subsurface_scatter(kg, sd, &emission_sd, &L_sample, &state, &rng, &ray, throughput);
+ kernel_branched_path_subsurface_scatter(kg, sd, &indirect_sd,
+ &emission_sd, &L_sample, &state, &rng, &ray, throughput);
}
#endif
@@ -161,7 +163,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
/* indirect light */
kernel_branched_path_surface_indirect_light(kg, &rng,
- sd, &emission_sd, throughput, 1.0f, &state, &L_sample);
+ sd, &indirect_sd, &emission_sd, throughput, 1.0f, &state, &L_sample);
}
}
#endif
@@ -480,12 +482,10 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
}
/* write output */
- float output_fac = is_aa_pass(type)? 1.0f/num_samples: 1.0f;
+ const float output_fac = is_aa_pass(type)? 1.0f/num_samples: 1.0f;
+ const float4 scaled_result = make_float4(out.x, out.y, out.z, 1.0f) * output_fac;
- if(sample == 0)
- output[i] = make_float4(out.x, out.y, out.z, 1.0f) * output_fac;
- else
- output[i] += make_float4(out.x, out.y, out.z, 1.0f) * output_fac;
+ output[i] = (sample == 0)? scaled_result: output[i] + scaled_result;
}
#endif /* __BAKING__ */
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index 7e6cdf93fb9..e06c68f2fc9 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -35,10 +35,10 @@ struct Intersection;
struct VolumeStep;
typedef struct KernelGlobals {
- texture_image_uchar4 texture_byte4_images[TEX_NUM_BYTE4_IMAGES_CPU];
- texture_image_float4 texture_float4_images[TEX_NUM_FLOAT4_IMAGES_CPU];
- texture_image_float texture_float_images[TEX_NUM_FLOAT_IMAGES_CPU];
- texture_image_uchar texture_byte_images[TEX_NUM_BYTE_IMAGES_CPU];
+ texture_image_uchar4 texture_byte4_images[TEX_NUM_BYTE4_CPU];
+ texture_image_float4 texture_float4_images[TEX_NUM_FLOAT4_CPU];
+ texture_image_float texture_float_images[TEX_NUM_FLOAT_CPU];
+ texture_image_uchar texture_byte_images[TEX_NUM_BYTE_CPU];
# define KERNEL_TEX(type, ttype, name) ttype name;
# define KERNEL_IMAGE_TEX(type, ttype, name)
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 5527d8aa861..0dded397ffa 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -53,6 +53,7 @@
CCL_NAMESPACE_BEGIN
ccl_device void kernel_path_indirect(KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *emission_sd,
RNG *rng,
Ray *ray,
@@ -61,9 +62,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
PathState *state,
PathRadiance *L)
{
- /* shader data memory used for both volumes and surfaces, saves stack space */
- ShaderData sd;
-
/* path iteration */
for(;;) {
/* intersect scene */
@@ -121,12 +119,12 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
VolumeSegment volume_segment;
shader_setup_from_volume(kg,
- &sd,
+ sd,
&volume_ray);
kernel_volume_decoupled_record(kg,
state,
&volume_ray,
- &sd,
+ sd,
&volume_segment,
heterogeneous);
@@ -149,7 +147,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* direct light sampling */
kernel_branched_path_volume_connect_light(kg,
rng,
- &sd,
+ sd,
emission_sd,
throughput,
state,
@@ -167,7 +165,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
result = kernel_volume_decoupled_scatter(kg,
state,
&volume_ray,
- &sd,
+ sd,
&throughput,
rphase,
rscatter,
@@ -182,7 +180,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
if(result == VOLUME_PATH_SCATTERED) {
if(kernel_path_volume_bounce(kg,
rng,
- &sd,
+ sd,
&throughput,
state,
L,
@@ -203,14 +201,14 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
{
/* integrate along volume segment with distance sampling */
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, state, &sd, &volume_ray, L, &throughput, rng, heterogeneous);
+ kg, state, sd, &volume_ray, L, &throughput, rng, heterogeneous);
# ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
/* direct lighting */
kernel_path_volume_connect_light(kg,
rng,
- &sd,
+ sd,
emission_sd,
throughput,
state,
@@ -219,7 +217,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* indirect light bounce */
if(kernel_path_volume_bounce(kg,
rng,
- &sd,
+ sd,
&throughput,
state,
L,
@@ -251,13 +249,13 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* setup shading */
shader_setup_from_ray(kg,
- &sd,
+ sd,
&isect,
ray);
float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF);
- shader_eval_surface(kg, &sd, state, rbsdf, state->flag, SHADER_CONTEXT_INDIRECT);
+ shader_eval_surface(kg, sd, state, rbsdf, state->flag, SHADER_CONTEXT_INDIRECT);
#ifdef __BRANCHED_PATH__
- shader_merge_closures(&sd);
+ shader_merge_closures(sd);
#endif
/* blurring of bsdf after bounces, for rays that have a small likelihood
@@ -267,15 +265,15 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
if(blur_pdf < 1.0f) {
float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f;
- shader_bsdf_blur(kg, &sd, blur_roughness);
+ shader_bsdf_blur(kg, sd, blur_roughness);
}
}
#ifdef __EMISSION__
/* emission */
- if(sd.flag & SD_EMISSION) {
+ if(sd->flag & SD_EMISSION) {
float3 emission = indirect_primitive_emission(kg,
- &sd,
+ sd,
isect.t,
state->flag,
state->ray_pdf);
@@ -305,30 +303,30 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
#ifdef __AO__
/* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
+ if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) {
float bsdf_u, bsdf_v;
path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
float ao_factor = kernel_data.background.ao_factor;
float3 ao_N;
- float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N);
+ float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
float3 ao_D;
float ao_pdf;
float3 ao_alpha = make_float3(0.0f, 0.0f, 0.0f);
sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
- if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
+ if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
Ray light_ray;
float3 ao_shadow;
- light_ray.P = ray_offset(sd.P, sd.Ng);
+ light_ray.P = ray_offset(sd->P, sd->Ng);
light_ray.D = ao_D;
light_ray.t = kernel_data.background.ao_distance;
# ifdef __OBJECT_MOTION__
- light_ray.time = sd.time;
+ light_ray.time = sd->time;
# endif
- light_ray.dP = sd.dP;
+ light_ray.dP = sd->dP;
light_ray.dD = differential3_zero();
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) {
@@ -346,9 +344,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
#ifdef __SUBSURFACE__
/* bssrdf scatter to a different location on the same object, replacing
* the closures with a diffuse BSDF */
- if(sd.flag & SD_BSSRDF) {
+ if(sd->flag & SD_BSSRDF) {
float bssrdf_probability;
- ShaderClosure *sc = subsurface_scatter_pick_closure(kg, &sd, &bssrdf_probability);
+ ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability);
/* modify throughput for picking bssrdf or bsdf */
throughput *= bssrdf_probability;
@@ -364,7 +362,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
PRNG_BSDF_U,
&bssrdf_u, &bssrdf_v);
subsurface_scatter_step(kg,
- &sd,
+ sd,
state,
state->flag,
sc,
@@ -380,7 +378,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
int all = kernel_data.integrator.sample_all_lights_indirect;
kernel_branched_path_surface_connect_light(kg,
rng,
- &sd,
+ sd,
emission_sd,
state,
throughput,
@@ -390,7 +388,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
}
#endif
- if(!kernel_path_surface_bounce(kg, rng, &sd, &throughput, state, L, ray))
+ if(!kernel_path_surface_bounce(kg, rng, sd, &throughput, state, L, ray))
break;
}
}
diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h
index b4dee220aa5..fdba1a7b025 100644
--- a/intern/cycles/kernel/kernel_path_branched.h
+++ b/intern/cycles/kernel/kernel_path_branched.h
@@ -64,8 +64,8 @@ ccl_device void kernel_branched_path_ao(KernelGlobals *kg,
/* bounce off surface and integrate indirect light */
ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg,
- RNG *rng, ShaderData *sd, ShaderData *emission_sd, float3 throughput,
- float num_samples_adjust, PathState *state, PathRadiance *L)
+ RNG *rng, ShaderData *sd, ShaderData *indirect_sd, ShaderData *emission_sd,
+ float3 throughput, float num_samples_adjust, PathState *state, PathRadiance *L)
{
for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
const ShaderClosure *sc = &ccl_fetch(sd, closure)[i];
@@ -112,6 +112,7 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
}
kernel_path_indirect(kg,
+ indirect_sd,
emission_sd,
rng,
&bsdf_ray,
@@ -131,6 +132,7 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
#ifdef __SUBSURFACE__
ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
ShaderData *sd,
+ ShaderData *indirect_sd,
ShaderData *emission_sd,
PathRadiance *L,
PathState *state,
@@ -222,6 +224,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
kg,
rng,
&bssrdf_sd,
+ indirect_sd,
emission_sd,
throughput,
num_samples_inv,
@@ -244,8 +247,8 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
/* shader data memory used for both volumes and surfaces, saves stack space */
ShaderData sd;
- /* shader data used by emission, shadows, volume stacks */
- ShaderData emission_sd;
+ /* shader data used by emission, shadows, volume stacks, indirect path */
+ ShaderData emission_sd, indirect_sd;
PathState state;
path_state_init(kg, &emission_sd, &state, rng, sample, &ray);
@@ -356,6 +359,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
&pray))
{
kernel_path_indirect(kg,
+ &indirect_sd,
&emission_sd,
rng,
&pray,
@@ -413,6 +417,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
&pray))
{
kernel_path_indirect(kg,
+ &indirect_sd,
&emission_sd,
rng,
&pray,
@@ -522,8 +527,8 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#ifdef __SUBSURFACE__
/* bssrdf scatter to a different location on the same object */
if(sd.flag & SD_BSSRDF) {
- kernel_branched_path_subsurface_scatter(kg, &sd, &emission_sd, &L, &state,
- rng, &ray, throughput);
+ kernel_branched_path_subsurface_scatter(kg, &sd, &indirect_sd, &emission_sd,
+ &L, &state, rng, &ray, throughput);
}
#endif
@@ -541,7 +546,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
/* indirect light */
kernel_branched_path_surface_indirect_light(kg, rng,
- &sd, &emission_sd, throughput, 1.0f, &hit_state, &L);
+ &sd, &indirect_sd, &emission_sd, throughput, 1.0f, &hit_state, &L);
/* continue in case of transparency */
throughput *= shader_bsdf_transparency(kg, &sd);
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index c8f6503cf58..1abbbb2ddad 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -126,8 +126,6 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, ShaderData *shadow_sd,
/* stop if all light is blocked */
if(is_zero(throughput)) {
/* free dynamic storage */
- if(hits != hits_stack)
- free(hits);
return true;
}
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index ba50d180acf..1ffcfb94a15 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -121,9 +121,7 @@ CCL_NAMESPACE_BEGIN
# define __OBJECT_MOTION__
# define __HAIR__
# define __BAKING__
-# ifdef __KERNEL_EXPERIMENTAL__
-# define __TRANSPARENT_SHADOWS__
-# endif
+# define __TRANSPARENT_SHADOWS__
# endif /* __KERNEL_OPENCL_AMD__ */
# ifdef __KERNEL_OPENCL_INTEL_CPU__
diff --git a/intern/cycles/kernel/kernels/cpu/kernel.cpp b/intern/cycles/kernel/kernels/cpu/kernel.cpp
index 365ce891354..d8a83f69685 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel.cpp
@@ -95,7 +95,7 @@ void kernel_tex_copy(KernelGlobals *kg,
int id = atoi(name + strlen("__tex_image_float4_"));
int array_index = id;
- if(array_index >= 0 && array_index < TEX_NUM_FLOAT4_IMAGES_CPU) {
+ if(array_index >= 0 && array_index < TEX_NUM_FLOAT4_CPU) {
tex = &kg->texture_float4_images[array_index];
}
@@ -109,9 +109,9 @@ void kernel_tex_copy(KernelGlobals *kg,
else if(strstr(name, "__tex_image_float")) {
texture_image_float *tex = NULL;
int id = atoi(name + strlen("__tex_image_float_"));
- int array_index = id - TEX_IMAGE_FLOAT_START_CPU;
+ int array_index = id - TEX_START_FLOAT_CPU;
- if(array_index >= 0 && array_index < TEX_NUM_FLOAT_IMAGES_CPU) {
+ if(array_index >= 0 && array_index < TEX_NUM_FLOAT_CPU) {
tex = &kg->texture_float_images[array_index];
}
@@ -125,9 +125,9 @@ void kernel_tex_copy(KernelGlobals *kg,
else if(strstr(name, "__tex_image_byte4")) {
texture_image_uchar4 *tex = NULL;
int id = atoi(name + strlen("__tex_image_byte4_"));
- int array_index = id - TEX_IMAGE_BYTE4_START_CPU;
+ int array_index = id - TEX_START_BYTE4_CPU;
- if(array_index >= 0 && array_index < TEX_NUM_BYTE4_IMAGES_CPU) {
+ if(array_index >= 0 && array_index < TEX_NUM_BYTE4_CPU) {
tex = &kg->texture_byte4_images[array_index];
}
@@ -141,9 +141,9 @@ void kernel_tex_copy(KernelGlobals *kg,
else if(strstr(name, "__tex_image_byte")) {
texture_image_uchar *tex = NULL;
int id = atoi(name + strlen("__tex_image_byte_"));
- int array_index = id - TEX_IMAGE_BYTE_START_CPU;
+ int array_index = id - TEX_START_BYTE_CPU;
- if(array_index >= 0 && array_index < TEX_NUM_BYTE_IMAGES_CPU) {
+ if(array_index >= 0 && array_index < TEX_NUM_BYTE_CPU) {
tex = &kg->texture_byte_images[array_index];
}
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
index 4807f96a0df..b10861ab857 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
@@ -23,24 +23,24 @@ CCL_NAMESPACE_BEGIN
ccl_device float4 kernel_tex_image_interp_impl(KernelGlobals *kg, int tex, float x, float y)
{
- if(tex >= TEX_IMAGE_BYTE_START_CPU)
- return kg->texture_byte_images[tex - TEX_IMAGE_BYTE_START_CPU].interp(x, y);
- else if(tex >= TEX_IMAGE_FLOAT_START_CPU)
- return kg->texture_float_images[tex - TEX_IMAGE_FLOAT_START_CPU].interp(x, y);
- else if(tex >= TEX_IMAGE_BYTE4_START_CPU)
- return kg->texture_byte4_images[tex - TEX_IMAGE_BYTE4_START_CPU].interp(x, y);
+ if(tex >= TEX_START_BYTE_CPU)
+ return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp(x, y);
+ else if(tex >= TEX_START_FLOAT_CPU)
+ return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp(x, y);
+ else if(tex >= TEX_START_BYTE4_CPU)
+ return kg->texture_byte4_images[tex - TEX_START_BYTE4_CPU].interp(x, y);
else
return kg->texture_float4_images[tex].interp(x, y);
}
ccl_device float4 kernel_tex_image_interp_3d_impl(KernelGlobals *kg, int tex, float x, float y, float z)
{
- if(tex >= TEX_IMAGE_BYTE_START_CPU)
- return kg->texture_byte_images[tex - TEX_IMAGE_BYTE_START_CPU].interp_3d(x, y, z);
- else if(tex >= TEX_IMAGE_FLOAT_START_CPU)
- return kg->texture_float_images[tex - TEX_IMAGE_FLOAT_START_CPU].interp_3d(x, y, z);
- else if(tex >= TEX_IMAGE_BYTE4_START_CPU)
- return kg->texture_byte4_images[tex - TEX_IMAGE_BYTE4_START_CPU].interp_3d(x, y, z);
+ if(tex >= TEX_START_BYTE_CPU)
+ return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp_3d(x, y, z);
+ else if(tex >= TEX_START_FLOAT_CPU)
+ return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp_3d(x, y, z);
+ else if(tex >= TEX_START_BYTE4_CPU)
+ return kg->texture_byte4_images[tex - TEX_START_BYTE4_CPU].interp_3d(x, y, z);
else
return kg->texture_float4_images[tex].interp_3d(x, y, z);
@@ -48,12 +48,12 @@ ccl_device float4 kernel_tex_image_interp_3d_impl(KernelGlobals *kg, int tex, fl
ccl_device float4 kernel_tex_image_interp_3d_ex_impl(KernelGlobals *kg, int tex, float x, float y, float z, int interpolation)
{
- if(tex >= TEX_IMAGE_BYTE_START_CPU)
- return kg->texture_byte_images[tex - TEX_IMAGE_BYTE_START_CPU].interp_3d_ex(x, y, z, interpolation);
- else if(tex >= TEX_IMAGE_FLOAT_START_CPU)
- return kg->texture_float_images[tex - TEX_IMAGE_FLOAT_START_CPU].interp_3d_ex(x, y, z, interpolation);
- else if(tex >= TEX_IMAGE_BYTE4_START_CPU)
- return kg->texture_byte4_images[tex - TEX_IMAGE_BYTE4_START_CPU].interp_3d_ex(x, y, z, interpolation);
+ if(tex >= TEX_START_BYTE_CPU)
+ return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp_3d_ex(x, y, z, interpolation);
+ else if(tex >= TEX_START_FLOAT_CPU)
+ return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp_3d_ex(x, y, z, interpolation);
+ else if(tex >= TEX_START_BYTE4_CPU)
+ return kg->texture_byte4_images[tex - TEX_START_BYTE4_CPU].interp_3d_ex(x, y, z, interpolation);
else
return kg->texture_float4_images[tex].interp_3d_ex(x, y, z, interpolation);
}
diff --git a/intern/cycles/kernel/shaders/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl
index 35e01178ba8..d5e0a7d4c8c 100644
--- a/intern/cycles/kernel/shaders/node_brick_texture.osl
+++ b/intern/cycles/kernel/shaders/node_brick_texture.osl
@@ -59,10 +59,10 @@ float brick(point p, float mortar_size, float bias,
shader node_brick_texture(
int use_mapping = 0,
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- float Offset = 0.5,
- int OffsetFrequency = 2,
- float Squash = 1.0,
- int SquashFrequency = 1,
+ float offset = 0.5,
+ int offset_frequency = 2,
+ float squash = 1.0,
+ int squash_frequency = 1,
point Vector = P,
color Color1 = 0.2,
color Color2 = 0.8,
@@ -84,7 +84,7 @@ shader node_brick_texture(
color Col = Color1;
Fac = brick(p * Scale, MortarSize, Bias, BrickWidth, RowHeight,
- Offset, OffsetFrequency, Squash, SquashFrequency, tint);
+ offset, offset_frequency, squash, squash_frequency, tint);
if (Fac != 1.0) {
float facm = 1.0 - tint;
diff --git a/intern/cycles/kernel/shaders/node_convert_from_color.osl b/intern/cycles/kernel/shaders/node_convert_from_color.osl
index 44074317f42..e95a17f6fa1 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_color.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_color.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_convert_from_color(
- color Color = 0.0,
- output string String = "",
- output float Val = 0.0,
- output int ValInt = 0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output point Point = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0))
+ color value_color = 0.0,
+ output string value_string = "",
+ output float value_float = 0.0,
+ output int value_int = 0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output point value_point = point(0.0, 0.0, 0.0),
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
- Val = Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722;
- ValInt = (int)(Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722);
- Vector = vector(Color[0], Color[1], Color[2]);
- Point = point(Color[0], Color[1], Color[2]);
- Normal = normal(Color[0], Color[1], Color[2]);
+ value_float = value_color[0] * 0.2126 + value_color[1] * 0.7152 + value_color[2] * 0.0722;
+ value_int = (int)(value_color[0] * 0.2126 + value_color[1] * 0.7152 + value_color[2] * 0.0722);
+ value_vector = vector(value_color[0], value_color[1], value_color[2]);
+ value_point = point(value_color[0], value_color[1], value_color[2]);
+ value_normal = normal(value_color[0], value_color[1], value_color[2]);
}
diff --git a/intern/cycles/kernel/shaders/node_convert_from_float.osl b/intern/cycles/kernel/shaders/node_convert_from_float.osl
index fc5c79c4c64..a5c2e3b26ad 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_float.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_float.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_convert_from_float(
- float Val = 0.0,
- output string String = "",
- output int ValInt = 0,
- output color Color = 0.0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output point Point = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0))
+ float value_float = 0.0,
+ output string value_string = "",
+ output int value_int = 0,
+ output color value_color = 0.0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output point value_point = point(0.0, 0.0, 0.0),
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
- ValInt = (int)Val;
- Color = color(Val, Val, Val);
- Vector = vector(Val, Val, Val);
- Point = point(Val, Val, Val);
- Normal = normal(Val, Val, Val);
+ value_int = (int)value_float;
+ value_color = color(value_float, value_float, value_float);
+ value_vector = vector(value_float, value_float, value_float);
+ value_point = point(value_float, value_float, value_float);
+ value_normal = normal(value_float, value_float, value_float);
}
diff --git a/intern/cycles/kernel/shaders/node_convert_from_int.osl b/intern/cycles/kernel/shaders/node_convert_from_int.osl
index 3c3785ebc0d..0e6ae711210 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_int.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_int.osl
@@ -17,19 +17,19 @@
#include "stdosl.h"
shader node_convert_from_int(
- int ValInt = 0,
- output string String = "",
- output float Val = 0.0,
- output color Color = 0.0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output point Point = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0))
+ int value_int = 0,
+ output string value_string = "",
+ output float value_float = 0.0,
+ output color value_color = 0.0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output point value_point = point(0.0, 0.0, 0.0),
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
- float f = (float)ValInt;
- Val = f;
- Color = color(f, f, f);
- Vector = vector(f, f, f);
- Point = point(f, f, f);
- Normal = normal(f, f, f);
+ float f = (float)value_int;
+ value_float = f;
+ value_color = color(f, f, f);
+ value_vector = vector(f, f, f);
+ value_point = point(f, f, f);
+ value_normal = normal(f, f, f);
}
diff --git a/intern/cycles/kernel/shaders/node_convert_from_normal.osl b/intern/cycles/kernel/shaders/node_convert_from_normal.osl
index 8ecc56ac8ce..7fffa7f6169 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_normal.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_normal.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_convert_from_normal(
- normal Normal = normal(0.0, 0.0, 0.0),
- output string String = "",
- output float Val = 0.0,
- output int ValInt = 0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output color Color = 0.0,
- output point Point = point(0.0, 0.0, 0.0))
+ normal value_normal = normal(0.0, 0.0, 0.0),
+ output string value_string = "",
+ output float value_float = 0.0,
+ output int value_int = 0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output color value_color = 0.0,
+ output point value_point = point(0.0, 0.0, 0.0))
{
- Val = (Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0);
- ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0));
- Vector = vector(Normal[0], Normal[1], Normal[2]);
- Color = color(Normal[0], Normal[1], Normal[2]);
- Point = point(Normal[0], Normal[1], Normal[2]);
+ value_float = (value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0);
+ value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
+ value_vector = vector(value_normal[0], value_normal[1], value_normal[2]);
+ value_color = color(value_normal[0], value_normal[1], value_normal[2]);
+ value_point = point(value_normal[0], value_normal[1], value_normal[2]);
}
diff --git a/intern/cycles/kernel/shaders/node_convert_from_point.osl b/intern/cycles/kernel/shaders/node_convert_from_point.osl
index e5913b7a1e4..9e4930296bb 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_point.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_point.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_convert_from_point(
- point Point = point(0.0, 0.0, 0.0),
- output string String = "",
- output float Val = 0.0,
- output int ValInt = 0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output color Color = 0.0,
- output normal Normal = normal(0.0, 0.0, 0.0))
+ point value_point = point(0.0, 0.0, 0.0),
+ output string value_string = "",
+ output float value_float = 0.0,
+ output int value_int = 0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output color value_color = 0.0,
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
- Val = (Point[0] + Point[1] + Point[2]) * (1.0 / 3.0);
- ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0));
- Vector = vector(Point[0], Point[1], Point[2]);
- Color = color(Point[0], Point[1], Point[2]);
- Normal = normal(Point[0], Point[1], Point[2]);
+ value_float = (value_point[0] + value_point[1] + value_point[2]) * (1.0 / 3.0);
+ value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
+ value_vector = vector(value_point[0], value_point[1], value_point[2]);
+ value_color = color(value_point[0], value_point[1], value_point[2]);
+ value_normal = normal(value_point[0], value_point[1], value_point[2]);
}
diff --git a/intern/cycles/kernel/shaders/node_convert_from_string.osl b/intern/cycles/kernel/shaders/node_convert_from_string.osl
index 0466734277b..cbc6653eada 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_string.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_string.osl
@@ -17,13 +17,13 @@
#include "stdosl.h"
shader node_convert_from_string(
- string String = "",
- output color Color = color(0.0, 0.0, 0.0),
- output float Val = 0.0,
- output int ValInt = 0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output point Point = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0))
+ string value_string = "",
+ output color value_color = color(0.0, 0.0, 0.0),
+ output float value_float = 0.0,
+ output int value_int = 0,
+ output vector value_vector = vector(0.0, 0.0, 0.0),
+ output point value_point = point(0.0, 0.0, 0.0),
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
}
diff --git a/intern/cycles/kernel/shaders/node_convert_from_vector.osl b/intern/cycles/kernel/shaders/node_convert_from_vector.osl
index 79c5cb04550..8bdca469b90 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_vector.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_vector.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_convert_from_vector(
- vector Vector = vector(0.0, 0.0, 0.0),
- output string String = "",
- output float Val = 0.0,
- output int ValInt = 0,
- output color Color = color(0.0, 0.0, 0.0),
- output point Point = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0))
+ vector value_vector = vector(0.0, 0.0, 0.0),
+ output string value_string = "",
+ output float value_float = 0.0,
+ output int value_int = 0,
+ output color value_color = color(0.0, 0.0, 0.0),
+ output point value_point = point(0.0, 0.0, 0.0),
+ output normal value_normal = normal(0.0, 0.0, 0.0))
{
- Val = (Vector[0] + Vector[1] + Vector[2]) * (1.0 / 3.0);
- ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0));
- Color = color(Vector[0], Vector[1], Vector[2]);
- Point = point(Vector[0], Vector[1], Vector[2]);
- Normal = normal(Vector[0], Vector[1], Vector[2]);
+ value_float = (value_vector[0] + value_vector[1] + value_vector[2]) * (1.0 / 3.0);
+ value_int = (int)((value_normal[0] + value_normal[1] + value_normal[2]) * (1.0 / 3.0));
+ value_color = color(value_vector[0], value_vector[1], value_vector[2]);
+ value_point = point(value_vector[0], value_vector[1], value_vector[2]);
+ value_normal = normal(value_vector[0], value_vector[1], value_vector[2]);
}
diff --git a/intern/cycles/kernel/shaders/node_gradient_texture.osl b/intern/cycles/kernel/shaders/node_gradient_texture.osl
index 52b49688ab3..69e2ee54bdf 100644
--- a/intern/cycles/kernel/shaders/node_gradient_texture.osl
+++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl
@@ -63,7 +63,7 @@ float gradient(point p, string type)
shader node_gradient_texture(
int use_mapping = 0,
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- string Type = "Linear",
+ string type = "Linear",
point Vector = P,
output float Fac = 0.0,
output color Color = 0.0)
@@ -73,7 +73,7 @@ shader node_gradient_texture(
if (use_mapping)
p = transform(mapping, p);
- Fac = gradient(p, Type);
+ Fac = gradient(p, type);
Color = color(Fac, Fac, Fac);
}
diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl
index d3a347b70db..d09174ff5d3 100644
--- a/intern/cycles/kernel/shaders/node_image_texture.osl
+++ b/intern/cycles/kernel/shaders/node_image_texture.osl
@@ -62,9 +62,9 @@ color image_texture_lookup(string filename,
int use_alpha,
int is_float,
string interpolation,
- string wrap)
+ string extension)
{
- color rgb = (color)texture(filename, u, 1.0 - v, "wrap", wrap, "interp", interpolation, "alpha", Alpha);
+ color rgb = (color)texture(filename, u, 1.0 - v, "wrap", extension, "interp", interpolation, "alpha", Alpha);
if (use_alpha) {
rgb = color_unpremultiply(rgb, Alpha);
diff --git a/intern/cycles/kernel/shaders/node_magic_texture.osl b/intern/cycles/kernel/shaders/node_magic_texture.osl
index 55992e3494c..8d6af391e04 100644
--- a/intern/cycles/kernel/shaders/node_magic_texture.osl
+++ b/intern/cycles/kernel/shaders/node_magic_texture.osl
@@ -93,7 +93,7 @@ color magic(point p, int n, float distortion)
shader node_magic_texture(
int use_mapping = 0,
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- int Depth = 2,
+ int depth = 2,
float Distortion = 5.0,
float Scale = 5.0,
point Vector = P,
@@ -105,7 +105,7 @@ shader node_magic_texture(
if (use_mapping)
p = transform(mapping, p);
- Color = magic(p * Scale, Depth, Distortion);
+ Color = magic(p * Scale, depth, Distortion);
Fac = (Color[0] + Color[1] + Color[2]) * (1.0 / 3.0);
}
diff --git a/intern/cycles/kernel/shaders/node_math.osl b/intern/cycles/kernel/shaders/node_math.osl
index 7eef97fd7e8..85eac0b97a6 100644
--- a/intern/cycles/kernel/shaders/node_math.osl
+++ b/intern/cycles/kernel/shaders/node_math.osl
@@ -50,7 +50,7 @@ float safe_log(float a, float b)
shader node_math(
string type = "Add",
- int Clamp = 0,
+ int use_clamp = 0,
float Value1 = 0.0,
float Value2 = 0.0,
output float Value = 0.0)
@@ -96,7 +96,7 @@ shader node_math(
else if (type == "Absolute")
Value = fabs(Value1);
- if (Clamp)
+ if (use_clamp)
Value = clamp(Value, 0.0, 1.0);
}
diff --git a/intern/cycles/kernel/shaders/node_mix.osl b/intern/cycles/kernel/shaders/node_mix.osl
index 9ef58e4cbba..4a66748ed6a 100644
--- a/intern/cycles/kernel/shaders/node_mix.osl
+++ b/intern/cycles/kernel/shaders/node_mix.osl
@@ -278,7 +278,7 @@ color node_mix_clamp(color col)
shader node_mix(
string type = "Mix",
- int Clamp = 0,
+ int use_clamp = 0,
float Fac = 0.5,
color Color1 = 0.0,
color Color2 = 0.0,
@@ -323,7 +323,7 @@ shader node_mix(
if (type == "Linear Light")
Color = node_mix_linear(t, Color1, Color2);
- if (Clamp)
+ if (use_clamp)
Color = node_mix_clamp(Color);
}
diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
index 4f95dec910a..2f9f62bcfe8 100644
--- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
@@ -187,7 +187,7 @@ float noise_musgrave_ridged_multi_fractal(point p, float H, float lacunarity,
shader node_musgrave_texture(
int use_mapping = 0,
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- string Type = "fBM",
+ string type = "fBM",
float Dimension = 2.0,
float Lacunarity = 1.0,
float Detail = 2.0,
@@ -210,15 +210,15 @@ shader node_musgrave_texture(
p = p * Scale;
- if (Type == "Multifractal")
+ if (type == "Multifractal")
Fac = intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
- else if (Type == "fBM")
+ else if (type == "fBM")
Fac = intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
- else if (Type == "Hybrid Multifractal")
+ else if (type == "Hybrid Multifractal")
Fac = intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
- else if (Type == "Ridged Multifractal")
+ else if (type == "Ridged Multifractal")
Fac = intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
- else if (Type == "Hetero Terrain")
+ else if (type == "Hetero Terrain")
Fac = intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, Offset);
Color = color(Fac, Fac, Fac);
diff --git a/intern/cycles/kernel/shaders/node_normal.osl b/intern/cycles/kernel/shaders/node_normal.osl
index 2d04978fc72..7307971eddd 100644
--- a/intern/cycles/kernel/shaders/node_normal.osl
+++ b/intern/cycles/kernel/shaders/node_normal.osl
@@ -17,12 +17,12 @@
#include "stdosl.h"
shader node_normal(
- normal Direction = normal(0.0, 0.0, 0.0),
+ normal direction = normal(0.0, 0.0, 0.0),
normal NormalIn = normal(0.0, 0.0, 0.0),
output normal NormalOut = normal(0.0, 0.0, 0.0),
output float Dot = 1.0)
{
- NormalOut = normalize(Direction);
+ NormalOut = normalize(direction);
Dot = dot(NormalOut, normalize(NormalIn));
}
diff --git a/intern/cycles/kernel/shaders/node_rgb_ramp.osl b/intern/cycles/kernel/shaders/node_rgb_ramp.osl
index 2ab6b6778b7..c0ae74d6b33 100644
--- a/intern/cycles/kernel/shaders/node_rgb_ramp.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_ramp.osl
@@ -20,7 +20,7 @@
shader node_rgb_ramp(
color ramp_color[] = {0.0},
float ramp_alpha[] = {0.0},
- int ramp_interpolate = 1,
+ int interpolate = 1,
float Fac = 0.0,
output color Color = 0.0,
@@ -38,7 +38,7 @@ shader node_rgb_ramp(
Color = ramp_color[i];
Alpha = ramp_alpha[i];
- if (ramp_interpolate && t > 0.0) {
+ if (interpolate && t > 0.0) {
Color = (1.0 - t) * Color + t * ramp_color[i + 1];
Alpha = (1.0 - t) * Alpha + t * ramp_alpha[i + 1];
}
diff --git a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
index a67333c5d4e..1877c7e595f 100644
--- a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
+++ b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
@@ -22,13 +22,13 @@ shader node_subsurface_scattering(
vector Radius = vector(0.1, 0.1, 0.1),
float TextureBlur = 0.0,
float Sharpness = 0.0,
- string Falloff = "Cubic",
+ string falloff = "Cubic",
normal Normal = N,
output closure color BSSRDF = 0)
{
- if (Falloff == "Gaussian")
+ if (falloff == "Gaussian")
BSSRDF = Color * bssrdf_gaussian(Normal, Scale * Radius, TextureBlur);
- else if (Falloff == "Cubic")
+ else if (falloff == "Cubic")
BSSRDF = Color * bssrdf_cubic(Normal, Scale * Radius, TextureBlur, Sharpness);
else
BSSRDF = Color * bssrdf_burley(Normal, Scale * Radius, TextureBlur, Color);
diff --git a/intern/cycles/kernel/shaders/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
index 29e143ae207..bacdd593c7c 100644
--- a/intern/cycles/kernel/shaders/node_voronoi_texture.osl
+++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
@@ -22,7 +22,7 @@
shader node_voronoi_texture(
int use_mapping = 0,
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- string Coloring = "Intensity",
+ string coloring = "Intensity",
float Scale = 5.0,
point Vector = P,
output float Fac = 0.0,
@@ -40,7 +40,7 @@ shader node_voronoi_texture(
voronoi(p * Scale, 1.0, da, pa);
/* Colored output */
- if (Coloring == "Intensity") {
+ if (coloring == "Intensity") {
Fac = fabs(da[0]);
Color = color(Fac);
}
diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl
index 59f61d3b46a..a07742faefc 100644
--- a/intern/cycles/kernel/shaders/node_wave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_wave_texture.osl
@@ -48,8 +48,8 @@ float wave(point p, string type, string profile, float detail, float distortion,
shader node_wave_texture(
int use_mapping = 0,
matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
- string Type = "Bands",
- string Profile = "Sine",
+ string type = "Bands",
+ string profile = "Sine",
float Scale = 5.0,
float Distortion = 0.0,
float Detail = 2.0,
@@ -63,7 +63,7 @@ shader node_wave_texture(
if (use_mapping)
p = transform(mapping, p);
- Fac = wave(p * Scale, Type, Profile, Detail, Distortion, DetailScale);
+ Fac = wave(p * Scale, type, profile, Detail, Distortion, DetailScale);
Color = Fac;
}
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 88397005b49..65512a0105c 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -365,8 +365,12 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
}
break;
}
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- case CLOSURE_BSDF_GLOSSY_TOON_ID: {
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
+#ifdef __CAUSTICS_TRICKS__
+ if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
+ break;
+#endif
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID: {
ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
if(sc) {
diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index 92d2b36bbb1..3d9ab405849 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -18,15 +18,15 @@ CCL_NAMESPACE_BEGIN
/* Float4 textures on various devices. */
#if defined(__KERNEL_CPU__)
-# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_IMAGES_CPU
+# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_CPU
#elif defined(__KERNEL_CUDA__)
# if __CUDA_ARCH__ < 300
-# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_IMAGES_CUDA
+# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_CUDA
# else
-# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER
+# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_CUDA_KEPLER
# endif
#else
-# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_IMAGES_OPENCL
+# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_OPENCL
#endif
#ifdef __KERNEL_OPENCL__
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index be87e35326e..e57d22b1b13 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -343,6 +343,11 @@ typedef enum NodeNormalMapSpace {
NODE_NORMAL_MAP_BLENDER_WORLD,
} NodeNormalMapSpace;
+typedef enum NodeImageColorSpace {
+ NODE_COLOR_SPACE_NONE = 0,
+ NODE_COLOR_SPACE_COLOR = 1,
+} NodeImageColorSpace;
+
typedef enum NodeImageProjection {
NODE_IMAGE_PROJ_FLAT = 0,
NODE_IMAGE_PROJ_BOX = 1,
@@ -350,6 +355,11 @@ typedef enum NodeImageProjection {
NODE_IMAGE_PROJ_TUBE = 3,
} NodeImageProjection;
+typedef enum NodeEnvironmentProjection {
+ NODE_ENVIRONMENT_EQUIRECTANGULAR = 0,
+ NODE_ENVIRONMENT_MIRROR_BALL = 1,
+} NodeEnvironmentProjection;
+
typedef enum NodeBumpOffset {
NODE_BUMP_OFFSET_CENTER,
NODE_BUMP_OFFSET_DX,
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index b7de83d89c1..71a3cba6811 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -51,13 +51,13 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix);
}
-void Attribute::reserve(int numverts, int numtris, int numsteps, int numcurves, int numkeys, bool resize)
+void Attribute::resize(int numverts, int numtris, int numsteps, int numcurves, int numkeys, bool reserve_only)
{
- if(resize) {
- buffer.resize(buffer_size(numverts, numtris, numsteps, numcurves, numkeys), 0);
+ if(reserve_only) {
+ buffer.reserve(buffer_size(numverts, numtris, numsteps, numcurves, numkeys));
}
else {
- buffer.reserve(buffer_size(numverts, numtris, numsteps, numcurves, numkeys));
+ buffer.resize(buffer_size(numverts, numtris, numsteps, numcurves, numkeys), 0);
}
}
@@ -263,7 +263,7 @@ AttributeSet::~AttributeSet()
{
}
-Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element, bool resize)
+Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
{
Attribute *attr = find(name);
@@ -291,9 +291,9 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme
/* this is weak .. */
if(triangle_mesh)
- attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, resize);
+ attr->resize(triangle_mesh->verts.size(), triangle_mesh->num_triangles(), triangle_mesh->motion_steps, 0, 0, false);
if(curve_mesh)
- attr->reserve(0, 0, curve_mesh->motion_steps, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), resize);
+ attr->resize(0, 0, curve_mesh->motion_steps, curve_mesh->num_curves(), curve_mesh->curve_keys.size(), false);
return attr;
}
@@ -448,13 +448,13 @@ Attribute *AttributeSet::find(AttributeRequest& req)
return find(req.std);
}
-void AttributeSet::reserve()
+void AttributeSet::resize(bool reserve_only)
{
foreach(Attribute& attr, attributes) {
if(triangle_mesh)
- attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, true);
+ attr.resize(triangle_mesh->verts.size(), triangle_mesh->num_triangles(), triangle_mesh->motion_steps, 0, 0, reserve_only);
if(curve_mesh)
- attr.reserve(0, 0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), true);
+ attr.resize(0, 0, 0, curve_mesh->num_curves(), curve_mesh->curve_keys.size(), reserve_only);
}
}
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index 01102d22aaa..41b3626afd3 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -58,7 +58,7 @@ public:
Attribute() {}
~Attribute();
void set(ustring name, TypeDesc type, AttributeElement element);
- void reserve(int numverts, int numfaces, int numsteps, int numcurves, int numkeys, bool resize);
+ void resize(int numverts, int numfaces, int numsteps, int numcurves, int numkeys, bool reserve_only);
size_t data_sizeof() const;
size_t element_size(int numverts, int numfaces, int numsteps, int numcurves, int numkeys) const;
@@ -104,7 +104,7 @@ public:
AttributeSet();
~AttributeSet();
- Attribute *add(ustring name, TypeDesc type, AttributeElement element, bool resize = true);
+ Attribute *add(ustring name, TypeDesc type, AttributeElement element);
Attribute *find(ustring name) const;
void remove(ustring name);
@@ -114,7 +114,7 @@ public:
Attribute *find(AttributeRequest& req);
- void reserve();
+ void resize(bool reserve_only = false);
void clear();
};
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index 6f8d1d1d461..20536b74e87 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -116,6 +116,11 @@ void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
}
+bool Background::modified(const Background& background)
+{
+ return !Node::equals(background);
+}
+
void Background::tag_update(Scene *scene)
{
scene->integrator->tag_update(scene);
diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h
index 843655b00a1..8029c6a9e80 100644
--- a/intern/cycles/render/background.h
+++ b/intern/cycles/render/background.h
@@ -50,6 +50,7 @@ public:
void device_update(Device *device, DeviceScene *dscene, Scene *scene);
void device_free(Device *device, DeviceScene *dscene);
+ bool modified(const Background& background);
void tag_update(Scene *scene);
};
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 5bf5e5113ef..13310a61761 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -177,7 +177,7 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre
device->mem_alloc(d_input, MEM_READ_ONLY);
device->mem_copy_to(d_input);
- device->mem_alloc(d_output, MEM_WRITE_ONLY);
+ device->mem_alloc(d_output, MEM_READ_WRITE);
DeviceTask task(DeviceTask::SHADER);
task.shader_input = d_input.device_pointer;
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index d992cac5312..2310798be2e 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -30,70 +30,126 @@
CCL_NAMESPACE_BEGIN
static float shutter_curve_eval(float x,
- float shutter_curve[RAMP_TABLE_SIZE])
+ array<float>& shutter_curve)
{
- x *= RAMP_TABLE_SIZE;
+ if (shutter_curve.size() == 0)
+ return 1.0f;
+
+ x *= shutter_curve.size();
int index = (int)x;
float frac = x - index;
- if(index < RAMP_TABLE_SIZE - 1) {
+ if(index < shutter_curve.size() - 1) {
return lerp(shutter_curve[index], shutter_curve[index + 1], frac);
}
else {
- return shutter_curve[RAMP_TABLE_SIZE - 1];
+ return shutter_curve[shutter_curve.size() - 1];
}
}
+NODE_DEFINE(Camera)
+{
+ NodeType* type = NodeType::add("camera", create);
+
+ SOCKET_FLOAT(shuttertime, "Shutter Time", 1.0f);
+
+ static NodeEnum motion_position_enum;
+ motion_position_enum.insert("start", MOTION_POSITION_START);
+ motion_position_enum.insert("center", MOTION_POSITION_CENTER);
+ motion_position_enum.insert("end", MOTION_POSITION_END);
+ SOCKET_ENUM(motion_position, "Motion Position", motion_position_enum, MOTION_POSITION_CENTER);
+
+ static NodeEnum rolling_shutter_type_enum;
+ rolling_shutter_type_enum.insert("none", ROLLING_SHUTTER_NONE);
+ rolling_shutter_type_enum.insert("top", ROLLING_SHUTTER_TOP);
+ SOCKET_ENUM(rolling_shutter_type, "Rolling Shutter Type", rolling_shutter_type_enum, ROLLING_SHUTTER_NONE);
+ SOCKET_FLOAT(rolling_shutter_duration, "Rolling Shutter Duration", 0.1f);
+
+ SOCKET_FLOAT_ARRAY(shutter_curve, "Shutter Curve", array<float>());
+
+ SOCKET_FLOAT(aperturesize, "Aperture Size", 0.0f);
+ SOCKET_FLOAT(focaldistance, "Focal Distance", 10.0f);
+ SOCKET_INT(blades, "Blades", 0);
+ SOCKET_FLOAT(bladesrotation, "Blades Rotation", 0.0f);
+
+ SOCKET_TRANSFORM(matrix, "Matrix", transform_identity());
+
+ SOCKET_FLOAT(aperture_ratio, "Aperture Ratio", 1.0f);
+
+ static NodeEnum type_enum;
+ type_enum.insert("perspective", CAMERA_PERSPECTIVE);
+ type_enum.insert("orthograph", CAMERA_ORTHOGRAPHIC);
+ type_enum.insert("panorama", CAMERA_PANORAMA);
+ SOCKET_ENUM(type, "Type", type_enum, CAMERA_PERSPECTIVE);
+
+ static NodeEnum panorama_type_enum;
+ panorama_type_enum.insert("equirectangular", PANORAMA_EQUIRECTANGULAR);
+ panorama_type_enum.insert("mirrorball", PANORAMA_MIRRORBALL);
+ panorama_type_enum.insert("fisheye_equidistant", PANORAMA_FISHEYE_EQUIDISTANT);
+ panorama_type_enum.insert("fisheye_equisolid", PANORAMA_FISHEYE_EQUISOLID);
+ SOCKET_ENUM(panorama_type, "Panorama Type", panorama_type_enum, PANORAMA_EQUIRECTANGULAR);
+
+ SOCKET_FLOAT(fisheye_fov, "Fisheye FOV", M_PI_F);
+ SOCKET_FLOAT(fisheye_lens, "Fisheye Lens", 10.5f);
+ SOCKET_FLOAT(latitude_min, "Latitude Min", -M_PI_2_F);
+ SOCKET_FLOAT(latitude_max, "Latitude Max", M_PI_2_F);
+ SOCKET_FLOAT(longitude_min, "Longitude Min", -M_PI_F);
+ SOCKET_FLOAT(longitude_max, "Longitude Max", M_PI_F);
+ SOCKET_FLOAT(fov, "FOV", M_PI_4_F);
+ SOCKET_FLOAT(fov_pre, "FOV Pre", M_PI_4_F);
+ SOCKET_FLOAT(fov_post, "FOV Post", M_PI_4_F);
+
+ static NodeEnum stereo_eye_enum;
+ stereo_eye_enum.insert("none", STEREO_NONE);
+ stereo_eye_enum.insert("left", STEREO_LEFT);
+ stereo_eye_enum.insert("right", STEREO_RIGHT);
+ SOCKET_ENUM(stereo_eye, "Stereo Eye", stereo_eye_enum, STEREO_NONE);
+
+ SOCKET_FLOAT(interocular_distance, "Interocular Distance", 0.065f);
+ SOCKET_FLOAT(convergence_distance, "Convergence Distance", 30.0f * 0.065f);
+
+ SOCKET_BOOLEAN(use_pole_merge, "Use Pole Merge", false);
+ SOCKET_FLOAT(pole_merge_angle_from, "Pole Merge Angle From", 60.0f * M_PI_F / 180.0f);
+ SOCKET_FLOAT(pole_merge_angle_to, "Pole Merge Angle To", 75.0f * M_PI_F / 180.0f);
+
+ SOCKET_FLOAT(sensorwidth, "Sensor Width", 0.036f);
+ SOCKET_FLOAT(sensorheight, "Sensor Height", 0.024f);
+
+ SOCKET_FLOAT(nearclip, "Near Clip", 1e-5f);
+ SOCKET_FLOAT(farclip, "Far Clip", 1e5f);
+
+ SOCKET_FLOAT(viewplane.left, "Viewplane Left", 0);
+ SOCKET_FLOAT(viewplane.right, "Viewplane Right", 0);
+ SOCKET_FLOAT(viewplane.bottom, "Viewplane Bottom", 0);
+ SOCKET_FLOAT(viewplane.top, "Viewplane Top", 0);
+
+ SOCKET_FLOAT(border.left, "Border Left", 0);
+ SOCKET_FLOAT(border.right, "Border Right", 0);
+ SOCKET_FLOAT(border.bottom, "Border Bottom", 0);
+ SOCKET_FLOAT(border.top, "Border Top", 0);
+
+ return type;
+}
+
Camera::Camera()
+: Node(node_type)
{
- shuttertime = 1.0f;
- motion_position = MOTION_POSITION_CENTER;
shutter_table_offset = TABLE_OFFSET_INVALID;
- aperturesize = 0.0f;
- focaldistance = 10.0f;
- blades = 0;
- bladesrotation = 0.0f;
-
- matrix = transform_identity();
+ width = 1024;
+ height = 512;
+ resolution = 1;
motion.pre = transform_identity();
motion.post = transform_identity();
use_motion = false;
use_perspective_motion = false;
- aperture_ratio = 1.0f;
-
- type = CAMERA_PERSPECTIVE;
- panorama_type = PANORAMA_EQUIRECTANGULAR;
- fisheye_fov = M_PI_F;
- fisheye_lens = 10.5f;
- latitude_min = -M_PI_2_F;
- latitude_max = M_PI_2_F;
- longitude_min = -M_PI_F;
- longitude_max = M_PI_F;
- fov = M_PI_4_F;
- fov_pre = fov_post = fov;
- stereo_eye = STEREO_NONE;
- interocular_distance = 0.065f;
- convergence_distance = 30.0f * 0.065f;
- use_pole_merge = false;
- pole_merge_angle_from = 60.0f * M_PI_F / 180.0f;
- pole_merge_angle_to = 75.0f * M_PI_F / 180.0f;
-
- sensorwidth = 0.036f;
- sensorheight = 0.024f;
-
- nearclip = 1e-5f;
- farclip = 1e5f;
-
- width = 1024;
- height = 512;
- resolution = 1;
+ shutter_curve.resize(RAMP_TABLE_SIZE);
+ for(int i = 0; i < shutter_curve.size(); ++i) {
+ shutter_curve[i] = 1.0f;
+ }
- viewplane.left = -((float)width/(float)height);
- viewplane.right = (float)width/(float)height;
- viewplane.bottom = -1.0f;
- viewplane.top = 1.0f;
+ compute_auto_viewplane();
screentoworld = transform_identity();
rastertoworld = transform_identity();
@@ -109,16 +165,6 @@ Camera::Camera()
need_device_update = true;
need_flags_update = true;
previous_need_motion = -1;
-
- /* Initialize shutter curve. */
- const int num_shutter_points = sizeof(shutter_curve) / sizeof(*shutter_curve);
- for(int i = 0; i < num_shutter_points; ++i) {
- shutter_curve[i] = 1.0f;
- }
-
- /* Initialize rolling shutter effect. */
- rolling_shutter_type = ROLLING_SHUTTER_NONE;
- rolling_shutter_duration = 0.1f;
}
Camera::~Camera()
@@ -438,38 +484,14 @@ void Camera::device_free(Device * /*device*/,
bool Camera::modified(const Camera& cam)
{
- return !((shuttertime == cam.shuttertime) &&
- (aperturesize == cam.aperturesize) &&
- (blades == cam.blades) &&
- (bladesrotation == cam.bladesrotation) &&
- (focaldistance == cam.focaldistance) &&
- (type == cam.type) &&
- (fov == cam.fov) &&
- (nearclip == cam.nearclip) &&
- (farclip == cam.farclip) &&
- (sensorwidth == cam.sensorwidth) &&
- (sensorheight == cam.sensorheight) &&
- // modified for progressive render
- // (width == cam.width) &&
- // (height == cam.height) &&
- (viewplane == cam.viewplane) &&
- (border == cam.border) &&
- (matrix == cam.matrix) &&
- (aperture_ratio == cam.aperture_ratio) &&
- (panorama_type == cam.panorama_type) &&
- (fisheye_fov == cam.fisheye_fov) &&
- (fisheye_lens == cam.fisheye_lens) &&
- (latitude_min == cam.latitude_min) &&
- (latitude_max == cam.latitude_max) &&
- (longitude_min == cam.longitude_min) &&
- (longitude_max == cam.longitude_max) &&
- (stereo_eye == cam.stereo_eye));
+ return !Node::equals(cam);
}
bool Camera::motion_modified(const Camera& cam)
{
return !((motion == cam.motion) &&
- (use_motion == cam.use_motion));
+ (use_motion == cam.use_motion) &&
+ (use_perspective_motion == cam.use_perspective_motion));
}
void Camera::tag_update()
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 57b9960e70b..141ef9cccef 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -19,6 +19,8 @@
#include "kernel_types.h"
+#include "node.h"
+
#include "util_boundbox.h"
#include "util_transform.h"
#include "util_types.h"
@@ -35,8 +37,10 @@ class Scene;
* Renderman, and Blender after remapping.
*/
-class Camera {
+class Camera : public Node {
public:
+ NODE_DECLARE;
+
/* Specifies an offset for the shutter's time interval. */
enum MotionPosition {
/* Shutter opens at the current frame. */
@@ -69,7 +73,7 @@ public:
/* motion blur */
float shuttertime;
MotionPosition motion_position;
- float shutter_curve[RAMP_TABLE_SIZE];
+ array<float> shutter_curve;
size_t shutter_table_offset;
/* ** Rolling shutter effect. ** */
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
index 3d9b4e1f347..e41967eebf5 100644
--- a/intern/cycles/render/curves.h
+++ b/intern/cycles/render/curves.h
@@ -63,23 +63,23 @@ public:
ParticleCurveData();
~ParticleCurveData();
- vector<int> psys_firstcurve;
- vector<int> psys_curvenum;
- vector<int> psys_shader;
-
- vector<float> psys_rootradius;
- vector<float> psys_tipradius;
- vector<float> psys_shape;
- vector<bool> psys_closetip;
-
- vector<int> curve_firstkey;
- vector<int> curve_keynum;
- vector<float> curve_length;
- vector<float3> curve_uv;
- vector<float3> curve_vcol;
-
- vector<float3> curvekey_co;
- vector<float> curvekey_time;
+ array<int> psys_firstcurve;
+ array<int> psys_curvenum;
+ array<int> psys_shader;
+
+ array<float> psys_rootradius;
+ array<float> psys_tipradius;
+ array<float> psys_shape;
+ array<bool> psys_closetip;
+
+ array<int> curve_firstkey;
+ array<int> curve_keynum;
+ array<float> curve_length;
+ array<float3> curve_uv;
+ array<float3> curve_vcol;
+
+ array<float3> curvekey_co;
+ array<float> curvekey_time;
};
/* HairSystem Manager */
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 12dce6ad999..e10a938e1eb 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -465,7 +465,7 @@ void Film::device_free(Device * /*device*/,
bool Film::modified(const Film& film)
{
- return Node::modified(film) || !Pass::equals(passes, film.passes);
+ return !Node::equals(film) || !Pass::equals(passes, film.passes);
}
void Film::tag_passes_update(Scene *scene, const array<Pass>& passes_)
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 24e4c9f33d5..29c0eec9b97 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -66,7 +66,7 @@ bool check_node_inputs_equals(const ShaderNode *node_a,
*input_b = node_b->inputs[i];
if(input_a->link == NULL && input_b->link == NULL) {
/* Unconnected inputs are expected to have the same value. */
- if(input_a->value != input_b->value) {
+ if(input_a->value() != input_b->value()) {
return false;
}
}
@@ -90,23 +90,22 @@ bool check_node_inputs_equals(const ShaderNode *node_a,
/* Input and Output */
-ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
+ShaderInput::ShaderInput(ShaderNode *parent_, const char *name, SocketType::Type type)
{
parent = parent_;
- name = name_;
- type = type_;
+ name_ = name;
+ type_ = type;
link = NULL;
- value = make_float3(0.0f, 0.0f, 0.0f);
+ value_ = make_float3(0.0f, 0.0f, 0.0f);
stack_offset = SVM_STACK_INVALID;
- default_value = NONE;
- usage = USE_ALL;
+ flags_ = 0;
}
-ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
+ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name, SocketType::Type type)
{
parent = parent_;
- name = name_;
- type = type_;
+ name_ = name;
+ type_ = type;
stack_offset = SVM_STACK_INVALID;
}
@@ -132,7 +131,7 @@ ShaderNode::~ShaderNode()
ShaderInput *ShaderNode::input(const char *name)
{
foreach(ShaderInput *socket, inputs) {
- if(strcmp(socket->name, name) == 0)
+ if(socket->name() == name)
return socket;
}
@@ -142,39 +141,50 @@ ShaderInput *ShaderNode::input(const char *name)
ShaderOutput *ShaderNode::output(const char *name)
{
foreach(ShaderOutput *socket, outputs)
- if(strcmp(socket->name, name) == 0)
+ if(socket->name() == name)
return socket;
return NULL;
}
-ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value, int usage)
+ShaderInput *ShaderNode::input(ustring name)
{
- ShaderInput *input = new ShaderInput(this, name, type);
- input->value.x = value;
- input->usage = usage;
- inputs.push_back(input);
- return input;
+ foreach(ShaderInput *socket, inputs) {
+ if(socket->name() == name)
+ return socket;
+ }
+
+ return NULL;
}
-ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value, int usage)
+ShaderOutput *ShaderNode::output(ustring name)
+{
+ foreach(ShaderOutput *socket, outputs)
+ if(socket->name() == name)
+ return socket;
+
+ return NULL;
+}
+
+ShaderInput *ShaderNode::add_input(const char *name, SocketType::Type type, float value, int flags)
{
ShaderInput *input = new ShaderInput(this, name, type);
- input->value = value;
- input->usage = usage;
+ input->value_.x = value;
+ input->flags_ = flags;
inputs.push_back(input);
return input;
}
-ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage)
+ShaderInput *ShaderNode::add_input(const char *name, SocketType::Type type, float3 value, int flags)
{
- ShaderInput *input = add_input(name, type);
- input->default_value = value;
- input->usage = usage;
+ ShaderInput *input = new ShaderInput(this, name, type);
+ input->value_ = value;
+ input->flags_ = flags;
+ inputs.push_back(input);
return input;
}
-ShaderOutput *ShaderNode::add_output(const char *name, ShaderSocketType type)
+ShaderOutput *ShaderNode::add_output(const char *name, SocketType::Type type)
{
ShaderOutput *output = new ShaderOutput(this, name, type);
outputs.push_back(output);
@@ -185,13 +195,13 @@ void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
foreach(ShaderInput *input, inputs) {
if(!input->link) {
- if(input->default_value == ShaderInput::TEXTURE_GENERATED) {
+ if(input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
if(shader->has_surface)
attributes->add(ATTR_STD_GENERATED);
if(shader->has_volume)
attributes->add(ATTR_STD_GENERATED_TRANSFORM);
}
- else if(input->default_value == ShaderInput::TEXTURE_UV) {
+ else if(input->flags() & SocketType::LINK_TEXTURE_UV) {
if(shader->has_surface)
attributes->add(ATTR_STD_UV);
}
@@ -256,18 +266,18 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
return;
}
- if(from->type != to->type) {
+ if(from->type() != to->type()) {
/* for closures we can't do automatic conversion */
- if(from->type == SHADER_SOCKET_CLOSURE || to->type == SHADER_SOCKET_CLOSURE) {
+ if(from->type() == SocketType::CLOSURE || to->type() == SocketType::CLOSURE) {
fprintf(stderr, "Cycles shader graph connect: can only connect closure to closure "
"(%s.%s to %s.%s).\n",
- from->parent->name.c_str(), from->name,
- to->parent->name.c_str(), to->name);
+ from->parent->name.c_str(), from->name().c_str(),
+ to->parent->name.c_str(), to->name().c_str());
return;
}
/* add automatic conversion node in case of type mismatch */
- ShaderNode *convert = add(new ConvertNode(from->type, to->type, true));
+ ShaderNode *convert = add(new ConvertNode(from->type(), to->type(), true));
connect(from, convert->inputs[0]);
connect(convert->outputs[0], to);
@@ -401,8 +411,8 @@ void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap)
/* find new input and output */
ShaderNode *nfrom = nnodemap[input->link->parent];
ShaderNode *nto = nnodemap[input->parent];
- ShaderOutput *noutput = nfrom->output(input->link->name);
- ShaderInput *ninput = nto->input(input->name);
+ ShaderOutput *noutput = nfrom->output(input->link->name());
+ ShaderInput *ninput = nto->input(input->name());
/* connect */
connect(noutput, ninput);
@@ -447,10 +457,10 @@ void ShaderGraph::remove_proxy_nodes()
vector<ShaderInput*> links = tonode->outputs[0]->links;
foreach(ShaderInput *autoin, links) {
- if(autoin->default_value == ShaderInput::NONE)
- all_links_removed = false;
- else
+ if(autoin->flags() & SocketType::DEFAULT_LINK_MASK)
disconnect(autoin);
+ else
+ all_links_removed = false;
}
if(all_links_removed)
@@ -460,8 +470,8 @@ void ShaderGraph::remove_proxy_nodes()
disconnect(to);
/* transfer the default input value to the target socket */
- to->set(input->value);
- to->set(input->value_string);
+ to->set(input->value());
+ to->set(input->value_string());
}
}
@@ -527,14 +537,13 @@ void ShaderGraph::constant_fold()
}
}
/* Optimize current node. */
- float3 optimized_value = make_float3(0.0f, 0.0f, 0.0f);
- if(node->constant_fold(this, output, &optimized_value)) {
- /* Apply optimized value to connected sockets. */
+ if(node->constant_fold(this, output, output->links[0])) {
+ /* Apply optimized value to other connected sockets and disconnect. */
vector<ShaderInput*> links(output->links);
- foreach(ShaderInput *input, links) {
- /* Assign value and disconnect the optimizedinput. */
- input->value = optimized_value;
- disconnect(input);
+ for(size_t i = 0; i < links.size(); i++) {
+ if(i > 0)
+ links[i]->set(links[0]->value());
+ disconnect(links[i]);
}
}
}
@@ -706,38 +715,38 @@ void ShaderGraph::default_inputs(bool do_osl)
foreach(ShaderNode *node, nodes) {
foreach(ShaderInput *input, node->inputs) {
- if(!input->link && ((input->usage & ShaderInput::USE_SVM) || do_osl)) {
- if(input->default_value == ShaderInput::TEXTURE_GENERATED) {
+ if(!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) {
+ if(input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
if(!texco)
texco = new TextureCoordinateNode();
connect(texco->output("Generated"), input);
}
- else if(input->default_value == ShaderInput::TEXTURE_UV) {
+ else if(input->flags() & SocketType::LINK_TEXTURE_UV) {
if(!texco)
texco = new TextureCoordinateNode();
connect(texco->output("UV"), input);
}
- else if(input->default_value == ShaderInput::INCOMING) {
+ else if(input->flags() & SocketType::LINK_INCOMING) {
if(!geom)
geom = new GeometryNode();
connect(geom->output("Incoming"), input);
}
- else if(input->default_value == ShaderInput::NORMAL) {
+ else if(input->flags() & SocketType::LINK_NORMAL) {
if(!geom)
geom = new GeometryNode();
connect(geom->output("Normal"), input);
}
- else if(input->default_value == ShaderInput::POSITION) {
+ else if(input->flags() & SocketType::LINK_POSITION) {
if(!geom)
geom = new GeometryNode();
connect(geom->output("Position"), input);
}
- else if(input->default_value == ShaderInput::TANGENT) {
+ else if(input->flags() & SocketType::LINK_TANGENT) {
if(!geom)
geom = new GeometryNode();
@@ -785,8 +794,8 @@ void ShaderGraph::refine_bump_nodes()
pair.second->bump = SHADER_BUMP_DY;
ShaderOutput *out = bump_input->link;
- ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name);
- ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name);
+ ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
+ ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
connect(out_dx, node->input("SampleX"));
connect(out_dy, node->input("SampleY"));
@@ -860,9 +869,9 @@ void ShaderGraph::bump_from_displacement()
ShaderNode *bump = add(new BumpNode());
ShaderOutput *out = displacement_in->link;
- ShaderOutput *out_center = nodes_center[out->parent]->output(out->name);
- ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name);
- ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name);
+ ShaderOutput *out_center = nodes_center[out->parent]->output(out->name());
+ ShaderOutput *out_dx = nodes_dx[out->parent]->output(out->name());
+ ShaderOutput *out_dy = nodes_dy[out->parent]->output(out->name());
connect(out_center, bump->input("SampleCenter"));
connect(out_dx, bump->input("SampleX"));
@@ -882,7 +891,7 @@ void ShaderGraph::bump_from_displacement()
continue;
}
foreach(ShaderInput *input, node->inputs) {
- if(!input->link && input->default_value == ShaderInput::NORMAL)
+ if(!input->link && (input->flags() & SocketType::LINK_NORMAL))
connect(set_normal->output("Normal"), input);
}
}
@@ -925,7 +934,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
if(fin->link)
connect(fin->link, fac_in);
else
- fac_in->value = fin->value;
+ fac_in->set(fin->value_float());
if(weight_out)
connect(weight_out, weight_in);
@@ -952,7 +961,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
return;
/* already has a weight connected to it? add weights */
- if(weight_in->link || weight_in->value.x != 0.0f) {
+ if(weight_in->link || weight_in->value_float() != 0.0f) {
ShaderNode *math_node = add(new MathNode());
ShaderInput *value1_in = math_node->input("Value1");
ShaderInput *value2_in = math_node->input("Value2");
@@ -960,12 +969,12 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
if(weight_in->link)
connect(weight_in->link, value1_in);
else
- value1_in->value = weight_in->value;
+ value1_in->set(weight_in->value_float());
if(weight_out)
connect(weight_out, value2_in);
else
- value2_in->value.x = 1.0f;
+ value2_in->set(1.0f);
weight_out = math_node->output("Value");
if(weight_in->link)
@@ -976,7 +985,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
if(weight_out)
connect(weight_out, weight_in);
else
- weight_in->value.x += 1.0f;
+ weight_in->set(weight_in->value_float() + 1.0f);
}
}
@@ -1024,7 +1033,7 @@ void ShaderGraph::dump_graph(const char *filename)
if(socket != node->inputs[0]) {
fprintf(fd, "|");
}
- fprintf(fd, "<IN_%p>%s", socket, socket->name);
+ fprintf(fd, "<IN_%p>%s", socket, socket->name().c_str());
}
fprintf(fd, "}|");
}
@@ -1044,7 +1053,7 @@ void ShaderGraph::dump_graph(const char *filename)
if(socket != node->outputs[0]) {
fprintf(fd, "|");
}
- fprintf(fd, "<OUT_%p>%s", socket, socket->name);
+ fprintf(fd, "<OUT_%p>%s", socket, socket->name().c_str());
}
fprintf(fd, "}");
}
@@ -1058,7 +1067,7 @@ void ShaderGraph::dump_graph(const char *filename)
"// CONNECTION: OUT_%p->IN_%p (%s:%s)\n",
output,
input,
- output->name, input->name);
+ output->name().c_str(), input->name().c_str());
fprintf(fd,
"\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n",
output->parent,
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index bd3f5ca689a..882e495df20 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -17,6 +17,8 @@
#ifndef __GRAPH_H__
#define __GRAPH_H__
+#include "node.h"
+
#include "kernel_types.h"
#include "util_list.h"
@@ -39,23 +41,6 @@ class SVMCompiler;
class OSLCompiler;
class OutputNode;
-/* Socket Type
- *
- * Data type for inputs and outputs */
-
-enum ShaderSocketType {
- SHADER_SOCKET_UNDEFINED,
-
- SHADER_SOCKET_FLOAT,
- SHADER_SOCKET_INT,
- SHADER_SOCKET_COLOR,
- SHADER_SOCKET_VECTOR,
- SHADER_SOCKET_POINT,
- SHADER_SOCKET_NORMAL,
- SHADER_SOCKET_CLOSURE,
- SHADER_SOCKET_STRING
-};
-
/* Bump
*
* For bump mapping, a node may be evaluated multiple times, using different
@@ -86,30 +71,6 @@ enum ShaderNodeSpecialType {
SHADER_SPECIAL_TYPE_BUMP,
};
-/* Enum
- *
- * Utility class for enum values. */
-
-class ShaderEnum {
-public:
- bool empty() const { return left.empty(); }
- void insert(const char *x, int y) {
- left[ustring(x)] = y;
- right[y] = ustring(x);
- }
-
- bool exists(ustring x) { return left.find(x) != left.end(); }
- bool exists(int y) { return right.find(y) != right.end(); }
-
- int operator[](const char *x) { return left[ustring(x)]; }
- int operator[](ustring x) { return left[x]; }
- ustring operator[](int y) { return right[y]; }
-
-protected:
- map<ustring, int> left;
- map<int, ustring> right;
-};
-
/* Input
*
* Input socket for a shader node. May be linked to an output or not. If not
@@ -118,39 +79,32 @@ protected:
class ShaderInput {
public:
- enum DefaultValue {
- TEXTURE_GENERATED,
- TEXTURE_UV,
- INCOMING,
- NORMAL,
- POSITION,
- TANGENT,
- NONE
- };
-
- enum Usage {
- USE_SVM = 1,
- USE_OSL = 2,
- USE_ALL = USE_SVM|USE_OSL
- };
-
- ShaderInput(ShaderNode *parent, const char *name, ShaderSocketType type);
- void set(const float3& v) { value = v; }
- void set(float f) { value = make_float3(f, 0, 0); }
- void set(const ustring v) { value_string = v; }
-
- const char *name;
- ShaderSocketType type;
+ ShaderInput(ShaderNode *parent, const char *name, SocketType::Type type);
+
+ ustring name() { return name_; }
+ int flags() { return flags_; }
+ SocketType::Type type() { return type_; }
+
+ void set(float f) { value_.x = f; }
+ void set(float3 f) { value_ = f; }
+ void set(int i) { value_.x = (float)i; }
+ void set(ustring s) { value_string_ = s; }
+
+ float3& value() { return value_; }
+ float& value_float() { return value_.x; }
+ ustring& value_string() { return value_string_; }
+
+ ustring name_;
+ SocketType::Type type_;
ShaderNode *parent;
ShaderOutput *link;
- DefaultValue default_value;
- float3 value;
- ustring value_string;
+ float3 value_;
+ ustring value_string_;
int stack_offset; /* for SVM compiler */
- int usage;
+ int flags_;
};
/* Output
@@ -159,12 +113,15 @@ public:
class ShaderOutput {
public:
- ShaderOutput(ShaderNode *parent, const char *name, ShaderSocketType type);
+ ShaderOutput(ShaderNode *parent, const char *name, SocketType::Type type);
- const char *name;
- ShaderNode *parent;
- ShaderSocketType type;
+ ustring name() { return name_; }
+ SocketType::Type type() { return type_; }
+ ustring name_;
+ SocketType::Type type_;
+
+ ShaderNode *parent;
vector<ShaderInput*> links;
int stack_offset; /* for SVM compiler */
@@ -182,11 +139,12 @@ public:
ShaderInput *input(const char *name);
ShaderOutput *output(const char *name);
+ ShaderInput *input(ustring name);
+ ShaderOutput *output(ustring name);
- ShaderInput *add_input(const char *name, ShaderSocketType type, float value=0.0f, int usage=ShaderInput::USE_ALL);
- ShaderInput *add_input(const char *name, ShaderSocketType type, float3 value, int usage=ShaderInput::USE_ALL);
- ShaderInput *add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage=ShaderInput::USE_ALL);
- ShaderOutput *add_output(const char *name, ShaderSocketType type);
+ ShaderInput *add_input(const char *name, SocketType::Type type, float value=0.0f, int flags=0);
+ ShaderInput *add_input(const char *name, SocketType::Type type, float3 value, int flags=0);
+ ShaderOutput *add_output(const char *name, SocketType::Type type);
virtual ShaderNode *clone() const = 0;
virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
@@ -195,7 +153,7 @@ public:
/* ** Node optimization ** */
/* Check whether the node can be replaced with single constant. */
- virtual bool constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 * /*optimized_value*/) { return false; }
+ virtual bool constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, ShaderInput * /*optimized*/) { return false; }
/* Simplify settings used by artists to the ones which are simpler to
* evaluate in the kernel but keep the final result unchanged.
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 6650c98aa38..71dc85f5f03 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -36,59 +36,58 @@ ImageManager::ImageManager(const DeviceInfo& info)
osl_texture_system = NULL;
animation_frame = 0;
- /* Set image limits */
+ /* In case of multiple devices used we need to know type of an actual
+ * compute device.
+ *
+ * NOTE: We assume that all the devices are same type, otherwise we'll
+ * be screwed on so many levels..
+ */
+ DeviceType device_type = info.type;
+ if (device_type == DEVICE_MULTI) {
+ device_type = info.multi_devices[0].type;
+ }
- /* CPU */
- if(info.type == DEVICE_CPU) {
- tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_CPU;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CPU;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_CPU;
- tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_CPU;
- tex_image_byte4_start = TEX_IMAGE_BYTE4_START_CPU;
- tex_image_float_start = TEX_IMAGE_FLOAT_START_CPU;
- tex_image_byte_start = TEX_IMAGE_BYTE_START_CPU;
+ /* Set image limits */
+#define SET_TEX_IMAGES_LIMITS(ARCH) \
+ { \
+ tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_ ## ARCH; \
+ tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_ ## ARCH; \
+ tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_ ## ARCH; \
+ tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_START_FLOAT4_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_BYTE4] = TEX_START_BYTE4_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_FLOAT] = TEX_START_FLOAT_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_BYTE] = TEX_START_BYTE_ ## ARCH; \
}
- /* CUDA (Fermi) */
- else if((info.type == DEVICE_CUDA || info.type == DEVICE_MULTI) && !info.has_bindless_textures) {
- tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_CUDA;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CUDA;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_CUDA;
- tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_CUDA;
- tex_image_byte4_start = TEX_IMAGE_BYTE4_START_CUDA;
- tex_image_float_start = TEX_IMAGE_FLOAT_START_CUDA;
- tex_image_byte_start = TEX_IMAGE_BYTE_START_CUDA;
+
+ if(device_type == DEVICE_CPU) {
+ SET_TEX_IMAGES_LIMITS(CPU);
}
- /* CUDA (Kepler and above) */
- else if((info.type == DEVICE_CUDA || info.type == DEVICE_MULTI) && info.has_bindless_textures) {
- tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_CUDA_KEPLER;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_CUDA_KEPLER;
- tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_CUDA_KEPLER;
- tex_image_byte4_start = TEX_IMAGE_BYTE4_START_CUDA_KEPLER;
- tex_image_float_start = TEX_IMAGE_FLOAT_START_CUDA_KEPLER;
- tex_image_byte_start = TEX_IMAGE_BYTE_START_CUDA_KEPLER;
+ else if(device_type == DEVICE_CUDA) {
+ if(info.has_bindless_textures) {
+ SET_TEX_IMAGES_LIMITS(CUDA_KEPLER);
+ }
+ else {
+ SET_TEX_IMAGES_LIMITS(CUDA);
+ }
}
- /* OpenCL */
- else if(info.pack_images) {
- tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_OPENCL;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_OPENCL;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_OPENCL;
- tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_OPENCL;
- tex_image_byte4_start = TEX_IMAGE_BYTE4_START_OPENCL;
- tex_image_float_start = TEX_IMAGE_FLOAT_START_OPENCL;
- tex_image_byte_start = TEX_IMAGE_BYTE_START_OPENCL;
+ else if(device_type == DEVICE_OPENCL) {
+ SET_TEX_IMAGES_LIMITS(OPENCL);
}
- /* Should never happen */
else {
- tex_num_images[IMAGE_DATA_TYPE_BYTE4] = 0;
+ /* Should not happen. */
tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = 0;
+ tex_num_images[IMAGE_DATA_TYPE_BYTE4] = 0;
tex_num_images[IMAGE_DATA_TYPE_FLOAT] = 0;
tex_num_images[IMAGE_DATA_TYPE_BYTE] = 0;
- tex_image_byte4_start = 0;
- tex_image_float_start = 0;
- tex_image_byte_start = 0;
+ tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_BYTE4] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_FLOAT] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_BYTE] = 0;
assert(0);
}
+
+#undef SET_TEX_IMAGES_LIMITS
}
ImageManager::~ImageManager()
@@ -207,34 +206,20 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
* to device ones and vice versa. */
int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type)
{
- if(type == IMAGE_DATA_TYPE_BYTE4)
- return slot + tex_image_byte4_start;
- else if(type == IMAGE_DATA_TYPE_FLOAT)
- return slot + tex_image_float_start;
- else if(type == IMAGE_DATA_TYPE_BYTE)
- return slot + tex_image_byte_start;
- else
- return slot;
+ return slot + tex_start_images[type];
}
int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *type)
{
- if(flat_slot >= tex_image_byte_start) {
- *type = IMAGE_DATA_TYPE_BYTE;
- return flat_slot - tex_image_byte_start;
- }
- else if(flat_slot >= tex_image_float_start) {
- *type = IMAGE_DATA_TYPE_FLOAT;
- return flat_slot - tex_image_float_start;
- }
- else if(flat_slot >= tex_image_byte4_start) {
- *type = IMAGE_DATA_TYPE_BYTE4;
- return flat_slot - tex_image_byte4_start;
- }
- else {
- *type = IMAGE_DATA_TYPE_FLOAT4;
- return flat_slot;
+ for(int i = IMAGE_DATA_NUM_TYPES - 1; i >= 0; i--) {
+ if(flat_slot >= tex_start_images[i]) {
+ *type = (ImageDataType)i;
+ return flat_slot - tex_start_images[i];
+ }
}
+
+ /* Should not happen. */
+ return flat_slot;
}
string ImageManager::name_from_type(int type)
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 2ab16dd8967..8735133fd91 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -96,9 +96,8 @@ public:
private:
int tex_num_images[IMAGE_DATA_NUM_TYPES];
- int tex_image_byte4_start;
- int tex_image_float_start;
- int tex_image_byte_start;
+ int tex_start_images[IMAGE_DATA_NUM_TYPES];
+
thread_mutex device_mutex;
int animation_frame;
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index 41e2571dc24..2a10eb474a4 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -204,6 +204,11 @@ void Integrator::device_free(Device *device, DeviceScene *dscene)
dscene->sobol_directions.clear();
}
+bool Integrator::modified(const Integrator& integrator)
+{
+ return !Node::equals(integrator);
+}
+
void Integrator::tag_update(Scene *scene)
{
foreach(Shader *shader, scene->shaders) {
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index a5cfb0c7863..39eaaf246d4 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -86,6 +86,7 @@ public:
void device_update(Device *device, DeviceScene *dscene, Scene *scene);
void device_free(Device *device, DeviceScene *dscene);
+ bool modified(const Integrator& integrator);
void tag_update(Scene *scene);
};
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index c20bf6b5e9e..9ef35820254 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -247,7 +247,8 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
/* count triangles */
if(have_emission) {
- for(size_t i = 0; i < mesh->triangles.size(); i++) {
+ size_t mesh_num_triangles = mesh->num_triangles();
+ for(size_t i = 0; i < mesh_num_triangles; i++) {
int shader_index = mesh->shader[i];
Shader *shader = (shader_index < mesh->used_shaders.size()) ?
mesh->used_shaders[shader_index] : scene->default_surface;
@@ -319,7 +320,8 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
use_light_visibility = true;
}
- for(size_t i = 0; i < mesh->triangles.size(); i++) {
+ size_t mesh_num_triangles = mesh->num_triangles();
+ for(size_t i = 0; i < mesh_num_triangles; i++) {
int shader_index = mesh->shader[i];
Shader *shader = (shader_index < mesh->used_shaders.size()) ?
mesh->used_shaders[shader_index] : scene->default_surface;
@@ -331,7 +333,7 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
distribution[offset].w = __int_as_float(object_id);
offset++;
- Mesh::Triangle t = mesh->triangles[i];
+ Mesh::Triangle t = mesh->get_triangle(i);
float3 p1 = mesh->verts[t.v[0]];
float3 p2 = mesh->verts[t.v[1]];
float3 p3 = mesh->verts[t.v[2]];
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index d26404035eb..755b16a51c7 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -51,14 +51,14 @@ void Mesh::Triangle::bounds_grow(const float3 *verts, BoundBox& bounds) const
/* Curve */
-void Mesh::Curve::bounds_grow(const int k, const float4 *curve_keys, BoundBox& bounds) const
+void Mesh::Curve::bounds_grow(const int k, const float3 *curve_keys, const float *curve_radius, BoundBox& bounds) const
{
float3 P[4];
- P[0] = float4_to_float3(curve_keys[max(first_key + k - 1,first_key)]);
- P[1] = float4_to_float3(curve_keys[first_key + k]);
- P[2] = float4_to_float3(curve_keys[first_key + k + 1]);
- P[3] = float4_to_float3(curve_keys[min(first_key + k + 2, first_key + num_keys - 1)]);
+ P[0] = curve_keys[max(first_key + k - 1,first_key)];
+ P[1] = curve_keys[first_key + k];
+ P[2] = curve_keys[first_key + k + 1];
+ P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
float3 lower;
float3 upper;
@@ -67,7 +67,7 @@ void Mesh::Curve::bounds_grow(const int k, const float4 *curve_keys, BoundBox& b
curvebounds(&lower.y, &upper.y, P, 1);
curvebounds(&lower.z, &upper.z, P, 2);
- float mr = max(curve_keys[first_key + k].w, curve_keys[first_key + k + 1].w);
+ float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
bounds.grow(lower, mr);
bounds.grow(upper, mr);
@@ -75,19 +75,42 @@ void Mesh::Curve::bounds_grow(const int k, const float4 *curve_keys, BoundBox& b
/* Mesh */
+NODE_DEFINE(Mesh)
+{
+ NodeType* type = NodeType::add("mesh", create);
+
+ static NodeEnum displacement_method_enum;
+ displacement_method_enum.insert("bump", DISPLACE_BUMP);
+ displacement_method_enum.insert("true", DISPLACE_TRUE);
+ displacement_method_enum.insert("both", DISPLACE_BOTH);
+ SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
+
+ SOCKET_INT(motion_steps, "Motion Steps", 3);
+ SOCKET_BOOLEAN(use_motion_blur, "Use Motion Blur", false);
+
+ SOCKET_INT_ARRAY(triangles, "Triangles", array<int>());
+ SOCKET_POINT_ARRAY(verts, "Vertices", array<float3>());
+ SOCKET_INT_ARRAY(shader, "Shader", array<int>());
+ SOCKET_BOOLEAN_ARRAY(smooth, "Smooth", array<bool>());
+
+ SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>());
+ SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>());
+ SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>());
+ SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>());
+
+ return type;
+}
+
Mesh::Mesh()
+: Node(node_type)
{
need_update = true;
need_update_rebuild = false;
transform_applied = false;
transform_negative_scaled = false;
transform_normal = transform_identity();
- displacement_method = DISPLACE_BUMP;
bounds = BoundBox::empty;
- motion_steps = 3;
- use_motion_blur = false;
-
bvh = NULL;
tri_offset = 0;
@@ -99,6 +122,8 @@ Mesh::Mesh()
attributes.triangle_mesh = this;
curve_attributes.curve_mesh = this;
+ geometry_flags = GEOMETRY_NONE;
+
has_volume = false;
has_surface_bssrdf = false;
}
@@ -108,21 +133,49 @@ Mesh::~Mesh()
delete bvh;
}
-void Mesh::reserve(int numverts, int numtris, int numcurves, int numcurvekeys)
+void Mesh::resize_mesh(int numverts, int numtris)
{
- /* reserve space to add verts and triangles later */
verts.resize(numverts);
- triangles.resize(numtris);
+ triangles.resize(numtris * 3);
shader.resize(numtris);
smooth.resize(numtris);
forms_quad.resize(numtris);
- curve_keys.resize(numcurvekeys);
- curves.resize(numcurves);
+ attributes.resize();
+}
+
+void Mesh::reserve_mesh(int numverts, int numtris)
+{
+ /* reserve space to add verts and triangles later */
+ verts.reserve(numverts);
+ triangles.reserve(numtris * 3);
+ shader.reserve(numtris);
+ smooth.reserve(numtris);
+
+ forms_quad.reserve(numtris);
- attributes.reserve();
- curve_attributes.reserve();
+ attributes.resize(true);
+}
+
+void Mesh::resize_curves(int numcurves, int numkeys)
+{
+ curve_keys.resize(numkeys);
+ curve_radius.resize(numkeys);
+ curve_first_key.resize(numcurves);
+ curve_shader.resize(numcurves);
+
+ curve_attributes.resize();
+}
+
+void Mesh::reserve_curves(int numcurves, int numkeys)
+{
+ curve_keys.reserve(numkeys);
+ curve_radius.reserve(numkeys);
+ curve_first_key.reserve(numcurves);
+ curve_shader.reserve(numcurves);
+
+ curve_attributes.resize(true);
}
void Mesh::clear()
@@ -136,7 +189,9 @@ void Mesh::clear()
forms_quad.clear();
curve_keys.clear();
- curves.clear();
+ curve_radius.clear();
+ curve_first_key.clear();
+ curve_shader.clear();
attributes.clear();
curve_attributes.clear();
@@ -151,7 +206,7 @@ void Mesh::clear()
int Mesh::split_vertex(int vertex)
{
/* copy vertex location and vertex attributes */
- verts.push_back(verts[vertex]);
+ add_vertex_slow(verts[vertex]);
foreach(Attribute& attr, attributes.attributes) {
if(attr.element == ATTR_ELEMENT_VERTEX) {
@@ -164,48 +219,36 @@ int Mesh::split_vertex(int vertex)
return verts.size() - 1;
}
-void Mesh::set_triangle(int i, int v0, int v1, int v2, int shader_, bool smooth_, bool forms_quad_)
+void Mesh::add_vertex(float3 P)
{
- Triangle tri;
- tri.v[0] = v0;
- tri.v[1] = v1;
- tri.v[2] = v2;
-
- triangles[i] = tri;
- shader[i] = shader_;
- smooth[i] = smooth_;
- forms_quad[i] = forms_quad_;
+ verts.push_back_reserved(P);
+}
+
+void Mesh::add_vertex_slow(float3 P)
+{
+ verts.push_back_slow(P);
}
void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_, bool forms_quad_)
{
- Triangle tri;
- tri.v[0] = v0;
- tri.v[1] = v1;
- tri.v[2] = v2;
-
- triangles.push_back(tri);
- shader.push_back(shader_);
- smooth.push_back(smooth_);
- forms_quad.push_back(forms_quad_);
+ triangles.push_back_reserved(v0);
+ triangles.push_back_reserved(v1);
+ triangles.push_back_reserved(v2);
+ shader.push_back_reserved(shader_);
+ smooth.push_back_reserved(smooth_);
+ forms_quad.push_back_reserved(forms_quad_);
}
void Mesh::add_curve_key(float3 co, float radius)
{
- float4 key = float3_to_float4(co);
- key.w = radius;
-
- curve_keys.push_back(key);
+ curve_keys.push_back_reserved(co);
+ curve_radius.push_back_reserved(radius);
}
-void Mesh::add_curve(int first_key, int num_keys, int shader)
+void Mesh::add_curve(int first_key, int shader)
{
- Curve curve;
- curve.first_key = first_key;
- curve.num_keys = num_keys;
- curve.shader = shader;
-
- curves.push_back(curve);
+ curve_first_key.push_back_reserved(first_key);
+ curve_shader.push_back_reserved(shader);
}
void Mesh::compute_bounds()
@@ -219,7 +262,7 @@ void Mesh::compute_bounds()
bnds.grow(verts[i]);
for(size_t i = 0; i < curve_keys_size; i++)
- bnds.grow(float4_to_float3(curve_keys[i]), curve_keys[i].w);
+ bnds.grow(curve_keys[i], curve_radius[i]);
Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if(use_motion_blur && attr) {
@@ -247,7 +290,7 @@ void Mesh::compute_bounds()
bnds.grow_safe(verts[i]);
for(size_t i = 0; i < curve_keys_size; i++)
- bnds.grow_safe(float4_to_float3(curve_keys[i]), curve_keys[i].w);
+ bnds.grow_safe(curve_keys[i], curve_radius[i]);
if(use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1);
@@ -301,15 +344,14 @@ void Mesh::add_face_normals()
float3 *fN = attr_fN->data_float3();
/* compute face normals */
- size_t triangles_size = triangles.size();
+ size_t triangles_size = num_triangles();
bool flip = transform_negative_scaled;
if(triangles_size) {
float3 *verts_ptr = &verts[0];
- Triangle *triangles_ptr = &triangles[0];
for(size_t i = 0; i < triangles_size; i++) {
- fN[i] = compute_face_normal(triangles_ptr[i], verts_ptr);
+ fN[i] = compute_face_normal(get_triangle(i), verts_ptr);
if(flip)
fN[i] = -fN[i];
@@ -329,7 +371,7 @@ void Mesh::add_vertex_normals()
{
bool flip = transform_negative_scaled;
size_t verts_size = verts.size();
- size_t triangles_size = triangles.size();
+ size_t triangles_size = num_triangles();
/* static vertex normals */
if(!attributes.find(ATTR_STD_VERTEX_NORMAL)) {
@@ -344,11 +386,10 @@ void Mesh::add_vertex_normals()
memset(vN, 0, verts.size()*sizeof(float3));
if(triangles_size) {
- Triangle *triangles_ptr = &triangles[0];
for(size_t i = 0; i < triangles_size; i++)
for(size_t j = 0; j < 3; j++)
- vN[triangles_ptr[i].v[j]] += fN[i];
+ vN[get_triangle(i).v[j]] += fN[i];
}
for(size_t i = 0; i < verts_size; i++) {
@@ -374,12 +415,10 @@ void Mesh::add_vertex_normals()
memset(mN, 0, verts.size()*sizeof(float3));
if(triangles_size) {
- Triangle *triangles_ptr = &triangles[0];
-
for(size_t i = 0; i < triangles_size; i++) {
for(size_t j = 0; j < 3; j++) {
- float3 fN = compute_face_normal(triangles_ptr[i], mP);
- mN[triangles_ptr[i].v[j]] += fN;
+ float3 fN = compute_face_normal(get_triangle(i), mP);
+ mN[get_triangle(i).v[j]] += fN;
}
}
}
@@ -402,8 +441,8 @@ void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal)
uint last_shader = -1;
bool last_smooth = false;
- size_t triangles_size = triangles.size();
- uint *shader_ptr = (shader.size())? &shader[0]: NULL;
+ size_t triangles_size = num_triangles();
+ int *shader_ptr = (shader.size())? &shader[0]: NULL;
bool do_transform = transform_applied;
Transform ntfm = transform_normal;
@@ -446,13 +485,11 @@ void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset)
}
}
- size_t triangles_size = triangles.size();
+ size_t triangles_size = num_triangles();
if(triangles_size) {
- Triangle *triangles_ptr = &triangles[0];
-
for(size_t i = 0; i < triangles_size; i++) {
- Triangle t = triangles_ptr[i];
+ Triangle t = get_triangle(i);
tri_vindex[i] = make_float4(
__int_as_float(t.v[0] + vert_offset),
@@ -466,27 +503,25 @@ void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset)
void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset)
{
size_t curve_keys_size = curve_keys.size();
- float4 *keys_ptr = NULL;
/* pack curve keys */
if(curve_keys_size) {
- keys_ptr = &curve_keys[0];
+ float3 *keys_ptr = &curve_keys[0];
+ float *radius_ptr = &curve_radius[0];
for(size_t i = 0; i < curve_keys_size; i++)
- curve_key_co[i] = keys_ptr[i];
+ curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]);
}
/* pack curve segments */
- size_t curve_num = curves.size();
+ size_t curve_num = num_curves();
if(curve_num) {
- Curve *curve_ptr = &curves[0];
- int shader_id = 0;
-
for(size_t i = 0; i < curve_num; i++) {
- Curve curve = curve_ptr[i];
- Shader *shader = (curve.shader < used_shaders.size()) ?
- used_shaders[curve.shader] : scene->default_surface;
+ Curve curve = get_curve(i);
+ int shader_id = curve_shader[i];
+ Shader *shader = (shader_id < used_shaders.size()) ?
+ used_shaders[shader_id] : scene->default_surface;
shader_id = scene->shader_manager->get_shader_id(shader, this, false);
curve_data[i] = make_float4(
@@ -732,7 +767,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
else
id = scene->shader_manager->get_attribute_id(req.std);
- if(mesh->triangles.size()) {
+ if(mesh->num_triangles()) {
attr_map[index].x = id;
attr_map[index].y = req.triangle_element;
attr_map[index].z = as_uint(req.triangle_offset);
@@ -747,7 +782,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
index++;
- if(mesh->curves.size()) {
+ if(mesh->num_curves()) {
attr_map[index].x = id;
attr_map[index].y = req.curve_element;
attr_map[index].z = as_uint(req.curve_offset);
@@ -793,9 +828,9 @@ static void update_attribute_element_size(Mesh *mesh,
if(mattr) {
size_t size = mattr->element_size(
mesh->verts.size(),
- mesh->triangles.size(),
+ mesh->num_triangles(),
mesh->motion_steps,
- mesh->curves.size(),
+ mesh->num_curves(),
mesh->curve_keys.size());
if(mattr->element == ATTR_ELEMENT_VOXEL) {
@@ -836,9 +871,9 @@ static void update_attribute_element_offset(Mesh *mesh,
/* store attribute data in arrays */
size_t size = mattr->element_size(
mesh->verts.size(),
- mesh->triangles.size(),
+ mesh->num_triangles(),
mesh->motion_steps,
- mesh->curves.size(),
+ mesh->num_curves(),
mesh->curve_keys.size());
if(mattr->element == ATTR_ELEMENT_VOXEL) {
@@ -1052,10 +1087,10 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
mesh->curve_offset = curve_size;
vert_size += mesh->verts.size();
- tri_size += mesh->triangles.size();
+ tri_size += mesh->num_triangles();
curve_key_size += mesh->curve_keys.size();
- curve_size += mesh->curves.size();
+ curve_size += mesh->num_curves();
}
if(tri_size != 0) {
@@ -1465,16 +1500,17 @@ void Mesh::tessellate(DiagSplit *split)
if(!forms_quad[f]) {
/* triangle */
LinearTrianglePatch patch;
+ Triangle triangle = get_triangle(f);
float3 *hull = patch.hull;
float3 *normals = patch.normals;
for(int i = 0; i < 3; i++) {
- hull[i] = verts[triangles[f].v[i]];
+ hull[i] = verts[triangle.v[i]];
}
if(smooth[f]) {
for(int i = 0; i < 3; i++) {
- normals[i] = vN[triangles[f].v[i]];
+ normals[i] = vN[triangle.v[i]];
}
}
else {
@@ -1488,19 +1524,21 @@ void Mesh::tessellate(DiagSplit *split)
else {
/* quad */
LinearQuadPatch patch;
+ Triangle triangle0 = get_triangle(f);
+ Triangle triangle1 = get_triangle(f+1);
float3 *hull = patch.hull;
float3 *normals = patch.normals;
- hull[0] = verts[triangles[f ].v[0]];
- hull[1] = verts[triangles[f ].v[1]];
- hull[3] = verts[triangles[f ].v[2]];
- hull[2] = verts[triangles[f+1].v[2]];
+ hull[0] = verts[triangle0.v[0]];
+ hull[1] = verts[triangle0.v[1]];
+ hull[3] = verts[triangle0.v[2]];
+ hull[2] = verts[triangle1.v[2]];
if(smooth[f]) {
- normals[0] = vN[triangles[f ].v[0]];
- normals[1] = vN[triangles[f ].v[1]];
- normals[3] = vN[triangles[f ].v[2]];
- normals[2] = vN[triangles[f+1].v[2]];
+ normals[0] = vN[triangle0.v[0]];
+ normals[1] = vN[triangle0.v[1]];
+ normals[3] = vN[triangle0.v[2]];
+ normals[2] = vN[triangle1.v[2]];
}
else {
for(int i = 0; i < 4; i++) {
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 557b664bff3..edad6d32f00 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -18,6 +18,7 @@
#define __MESH_H__
#include "attribute.h"
+#include "node.h"
#include "shader.h"
#include "util_boundbox.h"
@@ -42,8 +43,10 @@ class DiagSplit;
/* Mesh */
-class Mesh {
+class Mesh : public Node {
public:
+ NODE_DECLARE;
+
/* Mesh Triangle */
struct Triangle {
int v[3];
@@ -51,17 +54,41 @@ public:
void bounds_grow(const float3 *verts, BoundBox& bounds) const;
};
+ Triangle get_triangle(size_t i) const
+ {
+ Triangle tri = {{triangles[i*3 + 0], triangles[i*3 + 1], triangles[i*3 + 2]}};
+ return tri;
+ }
+
+ size_t num_triangles() const
+ {
+ return triangles.size() / 3;
+ }
+
/* Mesh Curve */
struct Curve {
int first_key;
int num_keys;
- uint shader;
int num_segments() { return num_keys - 1; }
- void bounds_grow(const int k, const float4 *curve_keys, BoundBox& bounds) const;
+ void bounds_grow(const int k, const float3 *curve_keys, const float *curve_radius, BoundBox& bounds) const;
};
+ Curve get_curve(size_t i) const
+ {
+ int first = curve_first_key[i];
+ int next_first = (i+1 < curve_first_key.size()) ? curve_first_key[i+1] : curve_keys.size();
+
+ Curve curve = {first, next_first - first};
+ return curve;
+ }
+
+ size_t num_curves() const
+ {
+ return curve_first_key.size();
+ }
+
/* Displacement */
enum DisplacementMethod {
DISPLACE_BUMP = 0,
@@ -71,8 +98,6 @@ public:
DISPLACE_NUM_METHODS,
};
- ustring name;
-
/* Mesh Data */
enum GeometryFlags {
GEOMETRY_NONE = 0,
@@ -82,17 +107,19 @@ public:
int geometry_flags; /* used to distinguish meshes with no verts
and meshed for which geometry is not created */
- vector<float3> verts;
- vector<Triangle> triangles;
- vector<uint> shader;
- vector<bool> smooth;
- vector<bool> forms_quad; /* used to tell if triangle is part of a quad patch */
+ array<int> triangles;
+ array<float3> verts;
+ array<int> shader;
+ array<bool> smooth;
+ array<bool> forms_quad; /* used to tell if triangle is part of a quad patch */
bool has_volume; /* Set in the device_update_flags(). */
bool has_surface_bssrdf; /* Set in the device_update_flags(). */
- vector<float4> curve_keys; /* co + radius */
- vector<Curve> curves;
+ array<float3> curve_keys;
+ array<float> curve_radius;
+ array<int> curve_first_key;
+ array<int> curve_shader;
vector<Shader*> used_shaders;
AttributeSet attributes;
@@ -123,12 +150,16 @@ public:
Mesh();
~Mesh();
- void reserve(int numverts, int numfaces, int numcurves, int numcurvekeys);
+ void resize_mesh(int numverts, int numfaces);
+ void reserve_mesh(int numverts, int numfaces);
+ void resize_curves(int numcurves, int numkeys);
+ void reserve_curves(int numcurves, int numkeys);
void clear();
- void set_triangle(int i, int v0, int v1, int v2, int shader, bool smooth, bool forms_quad = false);
+ void add_vertex(float3 P);
+ void add_vertex_slow(float3 P);
void add_triangle(int v0, int v1, int v2, int shader, bool smooth, bool forms_quad = false);
void add_curve_key(float3 loc, float radius);
- void add_curve(int first_key, int num_keys, int shader);
+ void add_curve(int first_key, int shader);
int split_vertex(int vertex);
void compute_bounds();
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index d19bf2084d7..95f46ff02a2 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -60,8 +60,9 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me
uint4 *d_input_data = d_input.resize(num_verts);
size_t d_input_size = 0;
- for(size_t i = 0; i < mesh->triangles.size(); i++) {
- Mesh::Triangle t = mesh->triangles[i];
+ size_t num_triangles = mesh->num_triangles();
+ for(size_t i = 0; i < num_triangles; i++) {
+ Mesh::Triangle t = mesh->get_triangle(i);
int shader_index = mesh->shader[i];
Shader *shader = (shader_index < mesh->used_shaders.size()) ?
mesh->used_shaders[shader_index] : scene->default_surface;
@@ -146,8 +147,8 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me
float4 *offset = (float4*)d_output.data_pointer;
Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- for(size_t i = 0; i < mesh->triangles.size(); i++) {
- Mesh::Triangle t = mesh->triangles[i];
+ for(size_t i = 0; i < num_triangles; i++) {
+ Mesh::Triangle t = mesh->get_triangle(i);
int shader_index = mesh->shader[i];
Shader *shader = (shader_index < mesh->used_shaders.size()) ?
mesh->used_shaders[shader_index] : scene->default_surface;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 998d9cf31dd..4656b3de9f3 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -30,9 +30,9 @@ CCL_NAMESPACE_BEGIN
/* Texture Mapping */
-static ShaderEnum texture_mapping_type_init()
+static NodeEnum texture_mapping_type_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Point", TextureMapping::POINT);
enm.insert("Texture", TextureMapping::TEXTURE);
@@ -42,9 +42,9 @@ static ShaderEnum texture_mapping_type_init()
return enm;
}
-static ShaderEnum texture_mapping_mapping_init()
+static NodeEnum texture_mapping_mapping_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("None", TextureMapping::NONE);
enm.insert("X", TextureMapping::X);
@@ -54,9 +54,9 @@ static ShaderEnum texture_mapping_mapping_init()
return enm;
}
-static ShaderEnum texture_mapping_projection_init()
+static NodeEnum texture_mapping_projection_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Flat", TextureMapping::FLAT);
enm.insert("Cube", TextureMapping::CUBE);
@@ -66,9 +66,9 @@ static ShaderEnum texture_mapping_projection_init()
return enm;
}
-ShaderEnum TextureMapping::type_enum = texture_mapping_type_init();
-ShaderEnum TextureMapping::mapping_enum = texture_mapping_mapping_init();
-ShaderEnum TextureMapping::projection_enum = texture_mapping_projection_init();
+NodeEnum TextureMapping::type_enum = texture_mapping_type_init();
+NodeEnum TextureMapping::mapping_enum = texture_mapping_mapping_init();
+NodeEnum TextureMapping::projection_enum = texture_mapping_projection_init();
TextureMapping::TextureMapping()
{
@@ -193,7 +193,7 @@ int TextureMapping::compile_begin(SVMCompiler& compiler, ShaderInput *vector_in)
{
if(!skip()) {
int offset_in = compiler.stack_assign(vector_in);
- int offset_out = compiler.stack_find_offset(SHADER_SOCKET_VECTOR);
+ int offset_out = compiler.stack_find_offset(SocketType::VECTOR);
compile(compiler, offset_in, offset_out);
@@ -206,7 +206,7 @@ int TextureMapping::compile_begin(SVMCompiler& compiler, ShaderInput *vector_in)
void TextureMapping::compile_end(SVMCompiler& compiler, ShaderInput *vector_in, int vector_offset)
{
if(!skip()) {
- compiler.stack_clear_offset(vector_in->type, vector_offset);
+ compiler.stack_clear_offset(vector_in->type(), vector_offset);
}
}
@@ -222,9 +222,9 @@ void TextureMapping::compile(OSLCompiler &compiler)
/* Image Texture */
-static ShaderEnum color_space_init()
+static NodeEnum color_space_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("None", 0);
enm.insert("Color", 1);
@@ -232,9 +232,9 @@ static ShaderEnum color_space_init()
return enm;
}
-static ShaderEnum image_projection_init()
+static NodeEnum image_projection_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Flat", NODE_IMAGE_PROJ_FLAT);
enm.insert("Box", NODE_IMAGE_PROJ_BOX);
@@ -259,8 +259,8 @@ static const char* get_osl_interpolation_parameter(InterpolationType interpolati
}
}
-ShaderEnum ImageTextureNode::color_space_enum = color_space_init();
-ShaderEnum ImageTextureNode::projection_enum = image_projection_init();
+NodeEnum ImageTextureNode::color_space_enum = color_space_init();
+NodeEnum ImageTextureNode::projection_enum = image_projection_init();
ImageTextureNode::ImageTextureNode()
: ImageSlotTextureNode("image_texture")
@@ -272,16 +272,16 @@ ImageTextureNode::ImageTextureNode()
use_alpha = true;
filename = "";
builtin_data = NULL;
- color_space = ustring("Color");
- projection = ustring("Flat");
+ color_space = NODE_COLOR_SPACE_COLOR;
+ projection = NODE_IMAGE_PROJ_FLAT;
interpolation = INTERPOLATION_LINEAR;
extension = EXTENSION_REPEAT;
projection_blend = 0.0f;
animated = false;
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Alpha", SHADER_SOCKET_FLOAT);
+ add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_UV);
+ add_output("Color", SocketType::COLOR);
+ add_output("Alpha", SocketType::FLOAT);
}
ImageTextureNode::~ImageTextureNode()
@@ -341,10 +341,10 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
}
if(slot != -1) {
- int srgb = (is_linear || color_space != "Color")? 0: 1;
+ int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR)? 0: 1;
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- if(projection != "Box") {
+ if(projection != NODE_IMAGE_PROJ_BOX) {
compiler.add_node(NODE_TEX_IMAGE,
slot,
compiler.encode_uchar4(
@@ -352,7 +352,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(alpha_out),
srgb),
- projection_enum[projection]);
+ projection);
}
else {
compiler.add_node(NODE_TEX_IMAGE_BOX,
@@ -421,7 +421,7 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
*/
compiler.parameter("filename", string_printf("@%d", slot).c_str());
}
- if(is_linear || color_space != "Color")
+ if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
compiler.parameter("color_space", "Linear");
else
compiler.parameter("color_space", "sRGB");
@@ -433,14 +433,14 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
switch(extension) {
case EXTENSION_EXTEND:
- compiler.parameter("wrap", "clamp");
+ compiler.parameter("extension", "clamp");
break;
case EXTENSION_CLIP:
- compiler.parameter("wrap", "black");
+ compiler.parameter("extension", "black");
break;
case EXTENSION_REPEAT:
default:
- compiler.parameter("wrap", "periodic");
+ compiler.parameter("extension", "periodic");
break;
}
@@ -449,9 +449,9 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
/* Environment Texture */
-static ShaderEnum env_projection_init()
+static NodeEnum env_projection_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Equirectangular", 0);
enm.insert("Mirror Ball", 1);
@@ -459,8 +459,8 @@ static ShaderEnum env_projection_init()
return enm;
}
-ShaderEnum EnvironmentTextureNode::color_space_enum = color_space_init();
-ShaderEnum EnvironmentTextureNode::projection_enum = env_projection_init();
+NodeEnum EnvironmentTextureNode::color_space_enum = color_space_init();
+NodeEnum EnvironmentTextureNode::projection_enum = env_projection_init();
EnvironmentTextureNode::EnvironmentTextureNode()
: ImageSlotTextureNode("environment_texture")
@@ -472,14 +472,14 @@ EnvironmentTextureNode::EnvironmentTextureNode()
use_alpha = true;
filename = "";
builtin_data = NULL;
- color_space = ustring("Color");
+ color_space = NODE_COLOR_SPACE_COLOR;
interpolation = INTERPOLATION_LINEAR;
- projection = ustring("Equirectangular");
+ projection = NODE_ENVIRONMENT_EQUIRECTANGULAR;
animated = false;
- add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Alpha", SHADER_SOCKET_FLOAT);
+ add_input("Vector", SocketType::VECTOR, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
+ add_output("Color", SocketType::COLOR);
+ add_output("Alpha", SocketType::FLOAT);
}
EnvironmentTextureNode::~EnvironmentTextureNode()
@@ -537,7 +537,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
}
if(slot != -1) {
- int srgb = (is_linear || color_space != "Color")? 0: 1;
+ int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR)? 0: 1;
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
compiler.add_node(NODE_TEX_ENVIRONMENT,
@@ -547,7 +547,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(alpha_out),
srgb),
- projection_enum[projection]);
+ projection);
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -602,8 +602,8 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler)
else {
compiler.parameter("filename", string_printf("@%d", slot).c_str());
}
- compiler.parameter("projection", projection);
- if(is_linear || color_space != "Color")
+ compiler.parameter("projection", projection_enum[projection]);
+ if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
compiler.parameter("color_space", "Linear");
else
compiler.parameter("color_space", "sRGB");
@@ -738,9 +738,9 @@ static void sky_texture_precompute_new(SunSky *sunsky, float3 dir, float turbidi
arhosekskymodelstate_free(sky_state);
}
-static ShaderEnum sky_type_init()
+static NodeEnum sky_type_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Preetham", NODE_SKY_OLD);
enm.insert("Hosek / Wilkie", NODE_SKY_NEW);
@@ -748,19 +748,19 @@ static ShaderEnum sky_type_init()
return enm;
}
-ShaderEnum SkyTextureNode::type_enum = sky_type_init();
+NodeEnum SkyTextureNode::type_enum = sky_type_init();
SkyTextureNode::SkyTextureNode()
: TextureNode("sky_texture")
{
- type = ustring("Hosek / Wilkie");
+ type = NODE_SKY_NEW;
sun_direction = make_float3(0.0f, 0.0f, 1.0f);
turbidity = 2.2f;
ground_albedo = 0.3f;
- add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("Vector", SocketType::VECTOR, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
+ add_output("Color", SocketType::COLOR);
}
void SkyTextureNode::compile(SVMCompiler& compiler)
@@ -769,15 +769,15 @@ void SkyTextureNode::compile(SVMCompiler& compiler)
ShaderOutput *color_out = output("Color");
SunSky sunsky;
- if(type_enum[type] == NODE_SKY_OLD)
+ if(type == NODE_SKY_OLD)
sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
- else if(type_enum[type] == NODE_SKY_NEW)
+ else if(type == NODE_SKY_NEW)
sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
else
assert(false);
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
- int sky_model = type_enum[type];
+ int sky_model = type;
compiler.stack_assign(color_out);
compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), sky_model);
@@ -799,14 +799,14 @@ void SkyTextureNode::compile(OSLCompiler& compiler)
SunSky sunsky;
- if(type_enum[type] == NODE_SKY_OLD)
+ if(type == NODE_SKY_OLD)
sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
- else if(type_enum[type] == NODE_SKY_NEW)
+ else if(type == NODE_SKY_NEW)
sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
else
assert(false);
- compiler.parameter("sky_model", type);
+ compiler.parameter("sky_model", type_enum[type]);
compiler.parameter("theta", sunsky.theta);
compiler.parameter("phi", sunsky.phi);
compiler.parameter_color("radiance", make_float3(sunsky.radiance_x, sunsky.radiance_y, sunsky.radiance_z));
@@ -818,9 +818,9 @@ void SkyTextureNode::compile(OSLCompiler& compiler)
/* Gradient Texture */
-static ShaderEnum gradient_type_init()
+static NodeEnum gradient_type_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Linear", NODE_BLEND_LINEAR);
enm.insert("Quadratic", NODE_BLEND_QUADRATIC);
@@ -833,16 +833,16 @@ static ShaderEnum gradient_type_init()
return enm;
}
-ShaderEnum GradientTextureNode::type_enum = gradient_type_init();
+NodeEnum GradientTextureNode::type_enum = gradient_type_init();
GradientTextureNode::GradientTextureNode()
: TextureNode("gradient_texture")
{
- type = ustring("Linear");
+ type = NODE_BLEND_LINEAR;
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ add_output("Color", SocketType::COLOR);
+ add_output("Fac", SocketType::FLOAT);
}
void GradientTextureNode::compile(SVMCompiler& compiler)
@@ -855,7 +855,7 @@ void GradientTextureNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_TEX_GRADIENT,
compiler.encode_uchar4(
- type_enum[type],
+ type,
vector_offset,
compiler.stack_assign_if_linked(fac_out),
compiler.stack_assign_if_linked(color_out)));
@@ -867,7 +867,7 @@ void GradientTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Type", type);
+ compiler.parameter("type", type_enum[type]);
compiler.add(this, "node_gradient_texture");
}
@@ -876,13 +876,13 @@ void GradientTextureNode::compile(OSLCompiler& compiler)
NoiseTextureNode::NoiseTextureNode()
: TextureNode("noise_texture")
{
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Detail", SHADER_SOCKET_FLOAT, 2.0f);
- add_input("Distortion", SHADER_SOCKET_FLOAT, 0.0f);
+ add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ add_input("Scale", SocketType::FLOAT, 1.0f);
+ add_input("Detail", SocketType::FLOAT, 2.0f);
+ add_input("Distortion", SocketType::FLOAT, 0.0f);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ add_output("Color", SocketType::COLOR);
+ add_output("Fac", SocketType::FLOAT);
}
void NoiseTextureNode::compile(SVMCompiler& compiler)
@@ -906,9 +906,9 @@ void NoiseTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out)));
compiler.add_node(
- __float_as_int(scale_in->value.x),
- __float_as_int(detail_in->value.x),
- __float_as_int(distortion_in->value.x));
+ __float_as_int(scale_in->value_float()),
+ __float_as_int(detail_in->value_float()),
+ __float_as_int(distortion_in->value_float()));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -922,9 +922,9 @@ void NoiseTextureNode::compile(OSLCompiler& compiler)
/* Voronoi Texture */
-static ShaderEnum voronoi_coloring_init()
+static NodeEnum voronoi_coloring_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Intensity", NODE_VORONOI_INTENSITY);
enm.insert("Cells", NODE_VORONOI_CELLS);
@@ -932,18 +932,18 @@ static ShaderEnum voronoi_coloring_init()
return enm;
}
-ShaderEnum VoronoiTextureNode::coloring_enum = voronoi_coloring_init();
+NodeEnum VoronoiTextureNode::coloring_enum = voronoi_coloring_init();
VoronoiTextureNode::VoronoiTextureNode()
: TextureNode("voronoi_texture")
{
- coloring = ustring("Intensity");
+ coloring = NODE_VORONOI_INTENSITY;
- add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
+ add_input("Scale", SocketType::FLOAT, 1.0f);
+ add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ add_output("Color", SocketType::COLOR);
+ add_output("Fac", SocketType::FLOAT);
}
void VoronoiTextureNode::compile(SVMCompiler& compiler)
@@ -956,13 +956,13 @@ void VoronoiTextureNode::compile(SVMCompiler& compiler)
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
compiler.add_node(NODE_TEX_VORONOI,
- coloring_enum[coloring],
+ coloring,
compiler.encode_uchar4(
compiler.stack_assign_if_linked(scale_in),
vector_offset,
compiler.stack_assign(fac_out),
compiler.stack_assign(color_out)),
- __float_as_int(scale_in->value.x));
+ __float_as_int(scale_in->value_float()));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -971,15 +971,15 @@ void VoronoiTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Coloring", coloring);
+ compiler.parameter("coloring", coloring_enum[coloring]);
compiler.add(this, "node_voronoi_texture");
}
/* Musgrave Texture */
-static ShaderEnum musgrave_type_init()
+static NodeEnum musgrave_type_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Multifractal", NODE_MUSGRAVE_MULTIFRACTAL);
enm.insert("fBM", NODE_MUSGRAVE_FBM);
@@ -990,23 +990,23 @@ static ShaderEnum musgrave_type_init()
return enm;
}
-ShaderEnum MusgraveTextureNode::type_enum = musgrave_type_init();
+NodeEnum MusgraveTextureNode::type_enum = musgrave_type_init();
MusgraveTextureNode::MusgraveTextureNode()
: TextureNode("musgrave_texture")
{
- type = ustring("fBM");
+ type = NODE_MUSGRAVE_FBM;
- add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Detail", SHADER_SOCKET_FLOAT, 2.0f);
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_input("Dimension", SHADER_SOCKET_FLOAT, 2.0f);
- add_input("Lacunarity", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Offset", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Gain", SHADER_SOCKET_FLOAT, 1.0f);
+ add_input("Scale", SocketType::FLOAT, 1.0f);
+ add_input("Detail", SocketType::FLOAT, 2.0f);
+ add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ add_input("Dimension", SocketType::FLOAT, 2.0f);
+ add_input("Lacunarity", SocketType::FLOAT, 1.0f);
+ add_input("Offset", SocketType::FLOAT, 0.0f);
+ add_input("Gain", SocketType::FLOAT, 1.0f);
- add_output("Fac", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_output("Fac", SocketType::FLOAT);
+ add_output("Color", SocketType::COLOR);
}
void MusgraveTextureNode::compile(SVMCompiler& compiler)
@@ -1025,7 +1025,7 @@ void MusgraveTextureNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_TEX_MUSGRAVE,
compiler.encode_uchar4(
- type_enum[type],
+ type,
vector_offset,
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out)),
@@ -1037,12 +1037,12 @@ void MusgraveTextureNode::compile(SVMCompiler& compiler)
compiler.encode_uchar4(
compiler.stack_assign_if_linked(gain_in),
compiler.stack_assign_if_linked(scale_in)));
- compiler.add_node(__float_as_int(dimension_in->value.x),
- __float_as_int(lacunarity_in->value.x),
- __float_as_int(detail_in->value.x),
- __float_as_int(offset_in->value.x));
- compiler.add_node(__float_as_int(gain_in->value.x),
- __float_as_int(scale_in->value.x));
+ compiler.add_node(__float_as_int(dimension_in->value_float()),
+ __float_as_int(lacunarity_in->value_float()),
+ __float_as_int(detail_in->value_float()),
+ __float_as_int(offset_in->value_float()));
+ compiler.add_node(__float_as_int(gain_in->value_float()),
+ __float_as_int(scale_in->value_float()));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -1051,16 +1051,16 @@ void MusgraveTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Type", type);
+ compiler.parameter("type", type_enum[type]);
compiler.add(this, "node_musgrave_texture");
}
/* Wave Texture */
-static ShaderEnum wave_type_init()
+static NodeEnum wave_type_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Bands", NODE_WAVE_BANDS);
enm.insert("Rings", NODE_WAVE_RINGS);
@@ -1068,9 +1068,9 @@ static ShaderEnum wave_type_init()
return enm;
}
-static ShaderEnum wave_profile_init()
+static NodeEnum wave_profile_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Sine", NODE_WAVE_PROFILE_SIN);
enm.insert("Saw", NODE_WAVE_PROFILE_SAW);
@@ -1078,23 +1078,23 @@ static ShaderEnum wave_profile_init()
return enm;
}
-ShaderEnum WaveTextureNode::type_enum = wave_type_init();
-ShaderEnum WaveTextureNode::profile_enum = wave_profile_init();
+NodeEnum WaveTextureNode::type_enum = wave_type_init();
+NodeEnum WaveTextureNode::profile_enum = wave_profile_init();
WaveTextureNode::WaveTextureNode()
: TextureNode("wave_texture")
{
- type = ustring("Bands");
- profile = ustring("Sine");
+ type = NODE_WAVE_BANDS;
+ profile = NODE_WAVE_PROFILE_SIN;
- add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Distortion", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Detail", SHADER_SOCKET_FLOAT, 2.0f);
- add_input("Detail Scale", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
+ add_input("Scale", SocketType::FLOAT, 1.0f);
+ add_input("Distortion", SocketType::FLOAT, 0.0f);
+ add_input("Detail", SocketType::FLOAT, 2.0f);
+ add_input("Detail Scale", SocketType::FLOAT, 1.0f);
+ add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ add_output("Color", SocketType::COLOR);
+ add_output("Fac", SocketType::FLOAT);
}
void WaveTextureNode::compile(SVMCompiler& compiler)
@@ -1111,7 +1111,7 @@ void WaveTextureNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_TEX_WAVE,
compiler.encode_uchar4(
- type_enum[type],
+ type,
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out),
compiler.stack_assign_if_linked(dscale_in)),
@@ -1120,13 +1120,13 @@ void WaveTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(scale_in),
compiler.stack_assign_if_linked(detail_in),
compiler.stack_assign_if_linked(distortion_in)),
- profile_enum[profile]);
+ profile);
compiler.add_node(
- __float_as_int(scale_in->value.x),
- __float_as_int(detail_in->value.x),
- __float_as_int(distortion_in->value.x),
- __float_as_int(dscale_in->value.x));
+ __float_as_int(scale_in->value_float()),
+ __float_as_int(detail_in->value_float()),
+ __float_as_int(distortion_in->value_float()),
+ __float_as_int(dscale_in->value_float()));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -1135,8 +1135,8 @@ void WaveTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Type", type);
- compiler.parameter("Profile", profile);
+ compiler.parameter("type", type_enum[type]);
+ compiler.parameter("profile", profile_enum[profile]);
compiler.add(this, "node_wave_texture");
}
@@ -1148,12 +1148,12 @@ MagicTextureNode::MagicTextureNode()
{
depth = 2;
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_input("Scale", SHADER_SOCKET_FLOAT, 5.0f);
- add_input("Distortion", SHADER_SOCKET_FLOAT, 1.0f);
+ add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ add_input("Scale", SocketType::FLOAT, 5.0f);
+ add_input("Distortion", SocketType::FLOAT, 1.0f);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ add_output("Color", SocketType::COLOR);
+ add_output("Fac", SocketType::FLOAT);
}
void MagicTextureNode::compile(SVMCompiler& compiler)
@@ -1176,8 +1176,8 @@ void MagicTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(scale_in),
compiler.stack_assign_if_linked(distortion_in)));
compiler.add_node(
- __float_as_int(scale_in->value.x),
- __float_as_int(distortion_in->value.x));
+ __float_as_int(scale_in->value_float()),
+ __float_as_int(distortion_in->value_float()));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -1186,7 +1186,7 @@ void MagicTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Depth", depth);
+ compiler.parameter("depth", depth);
compiler.add(this, "node_magic_texture");
}
@@ -1195,13 +1195,13 @@ void MagicTextureNode::compile(OSLCompiler& compiler)
CheckerTextureNode::CheckerTextureNode()
: TextureNode("checker_texture")
{
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_input("Color1", SHADER_SOCKET_COLOR);
- add_input("Color2", SHADER_SOCKET_COLOR);
- add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
+ add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ add_input("Color1", SocketType::COLOR);
+ add_input("Color2", SocketType::COLOR);
+ add_input("Scale", SocketType::FLOAT, 1.0f);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ add_output("Color", SocketType::COLOR);
+ add_output("Fac", SocketType::FLOAT);
}
void CheckerTextureNode::compile(SVMCompiler& compiler)
@@ -1225,7 +1225,7 @@ void CheckerTextureNode::compile(SVMCompiler& compiler)
compiler.encode_uchar4(
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out)),
- __float_as_int(scale_in->value.x));
+ __float_as_int(scale_in->value_float()));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -1247,18 +1247,18 @@ BrickTextureNode::BrickTextureNode()
squash = 1.0f;
squash_frequency = 2;
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_input("Color1", SHADER_SOCKET_COLOR);
- add_input("Color2", SHADER_SOCKET_COLOR);
- add_input("Mortar", SHADER_SOCKET_COLOR);
- add_input("Scale", SHADER_SOCKET_FLOAT, 5.0f);
- add_input("Mortar Size", SHADER_SOCKET_FLOAT, 0.02f);
- add_input("Bias", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Brick Width", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Row Height", SHADER_SOCKET_FLOAT, 0.25f);
+ add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
+ add_input("Color1", SocketType::COLOR);
+ add_input("Color2", SocketType::COLOR);
+ add_input("Mortar", SocketType::COLOR);
+ add_input("Scale", SocketType::FLOAT, 5.0f);
+ add_input("Mortar Size", SocketType::FLOAT, 0.02f);
+ add_input("Bias", SocketType::FLOAT, 0.0f);
+ add_input("Brick Width", SocketType::FLOAT, 0.5f);
+ add_input("Row Height", SocketType::FLOAT, 0.25f);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ add_output("Color", SocketType::COLOR);
+ add_output("Fac", SocketType::FLOAT);
}
void BrickTextureNode::compile(SVMCompiler& compiler)
@@ -1295,12 +1295,12 @@ void BrickTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(fac_out)));
compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency),
- __float_as_int(scale_in->value.x),
- __float_as_int(mortar_size_in->value.x),
- __float_as_int(bias_in->value.x));
+ __float_as_int(scale_in->value_float()),
+ __float_as_int(mortar_size_in->value_float()),
+ __float_as_int(bias_in->value_float()));
- compiler.add_node(__float_as_int(brick_width_in->value.x),
- __float_as_int(row_height_in->value.x),
+ compiler.add_node(__float_as_int(brick_width_in->value_float()),
+ __float_as_int(row_height_in->value_float()),
__float_as_int(offset),
__float_as_int(squash));
@@ -1311,18 +1311,18 @@ void BrickTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Offset", offset);
- compiler.parameter("OffsetFrequency", offset_frequency);
- compiler.parameter("Squash", squash);
- compiler.parameter("SquashFrequency", squash_frequency);
+ compiler.parameter("offset", offset);
+ compiler.parameter("offset_frequency", offset_frequency);
+ compiler.parameter("squash", squash);
+ compiler.parameter("squash_frequency", squash_frequency);
compiler.add(this, "node_brick_texture");
}
/* Point Density Texture */
-static ShaderEnum point_density_space_init()
+static NodeEnum point_density_space_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Object", NODE_TEX_VOXEL_SPACE_OBJECT);
enm.insert("World", NODE_TEX_VOXEL_SPACE_WORLD);
@@ -1330,7 +1330,7 @@ static ShaderEnum point_density_space_init()
return enm;
}
-ShaderEnum PointDensityTextureNode::space_enum = point_density_space_init();
+NodeEnum PointDensityTextureNode::space_enum = point_density_space_init();
PointDensityTextureNode::PointDensityTextureNode()
: ShaderNode("point_density")
@@ -1338,15 +1338,15 @@ PointDensityTextureNode::PointDensityTextureNode()
image_manager = NULL;
slot = -1;
filename = "";
- space = ustring("Object");
+ space = NODE_TEX_VOXEL_SPACE_OBJECT;
builtin_data = NULL;
interpolation = INTERPOLATION_LINEAR;
tfm = transform_identity();
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::POSITION);
- add_output("Density", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("Vector", SocketType::POINT, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_POSITION);
+ add_output("Density", SocketType::FLOAT);
+ add_output("Color", SocketType::COLOR);
}
PointDensityTextureNode::~PointDensityTextureNode()
@@ -1405,8 +1405,8 @@ void PointDensityTextureNode::compile(SVMCompiler& compiler)
compiler.encode_uchar4(compiler.stack_assign(vector_in),
compiler.stack_assign_if_linked(density_out),
compiler.stack_assign_if_linked(color_out),
- space_enum[space]));
- if(space == "World") {
+ space));
+ if(space == NODE_TEX_VOXEL_SPACE_WORLD) {
compiler.add_node(tfm.x);
compiler.add_node(tfm.y);
compiler.add_node(tfm.z);
@@ -1453,7 +1453,7 @@ void PointDensityTextureNode::compile(OSLCompiler& compiler)
if(slot != -1) {
compiler.parameter("filename", string_printf("@%d", slot).c_str());
}
- if(space == "World") {
+ if(space == NODE_TEX_VOXEL_SPACE_WORLD) {
compiler.parameter("mapping", transform_transpose(tfm));
compiler.parameter("use_mapping", 1);
}
@@ -1481,9 +1481,9 @@ NormalNode::NormalNode()
{
direction = make_float3(0.0f, 0.0f, 1.0f);
- add_input("Normal", SHADER_SOCKET_NORMAL);
- add_output("Normal", SHADER_SOCKET_NORMAL);
- add_output("Dot", SHADER_SOCKET_FLOAT);
+ add_input("Normal", SocketType::NORMAL);
+ add_output("Normal", SocketType::NORMAL);
+ add_output("Dot", SocketType::FLOAT);
}
void NormalNode::compile(SVMCompiler& compiler)
@@ -1504,7 +1504,7 @@ void NormalNode::compile(SVMCompiler& compiler)
void NormalNode::compile(OSLCompiler& compiler)
{
- compiler.parameter_normal("Direction", direction);
+ compiler.parameter_normal("direction", direction);
compiler.add(this, "node_normal");
}
@@ -1513,8 +1513,8 @@ void NormalNode::compile(OSLCompiler& compiler)
MappingNode::MappingNode()
: ShaderNode("mapping")
{
- add_input("Vector", SHADER_SOCKET_POINT);
- add_output("Vector", SHADER_SOCKET_POINT);
+ add_input("Vector", SocketType::POINT);
+ add_output("Vector", SocketType::POINT);
}
void MappingNode::compile(SVMCompiler& compiler)
@@ -1536,9 +1536,41 @@ void MappingNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_mapping");
}
+/* RGBToBW */
+
+RGBToBWNode::RGBToBWNode()
+: ShaderNode("rgb_to_bw")
+{
+ add_input("Color", SocketType::COLOR);
+ add_output("Val", SocketType::FLOAT);
+}
+
+bool RGBToBWNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized)
+{
+ if(inputs[0]->link == NULL) {
+ optimized->set(linear_rgb_to_gray(inputs[0]->value()));
+ return true;
+ }
+
+ return false;
+}
+
+void RGBToBWNode::compile(SVMCompiler& compiler)
+{
+ compiler.add_node(NODE_CONVERT,
+ NODE_CONVERT_CF,
+ compiler.stack_assign(inputs[0]),
+ compiler.stack_assign(outputs[0]));
+}
+
+void RGBToBWNode::compile(OSLCompiler& compiler)
+{
+ compiler.add(this, "node_convert_from_color");
+}
+
/* Convert */
-ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_, bool autoconvert)
+ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool autoconvert)
: ShaderNode("convert")
{
from = from_;
@@ -1551,92 +1583,72 @@ ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_, bool auto
special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT;
}
- if(from == SHADER_SOCKET_FLOAT)
- add_input("Val", SHADER_SOCKET_FLOAT);
- else if(from == SHADER_SOCKET_INT)
- add_input("ValInt", SHADER_SOCKET_INT);
- else if(from == SHADER_SOCKET_COLOR)
- add_input("Color", SHADER_SOCKET_COLOR);
- else if(from == SHADER_SOCKET_VECTOR)
- add_input("Vector", SHADER_SOCKET_VECTOR);
- else if(from == SHADER_SOCKET_POINT)
- add_input("Point", SHADER_SOCKET_POINT);
- else if(from == SHADER_SOCKET_NORMAL)
- add_input("Normal", SHADER_SOCKET_NORMAL);
- else if(from == SHADER_SOCKET_STRING)
- add_input("String", SHADER_SOCKET_STRING);
- else if(from == SHADER_SOCKET_CLOSURE)
- add_input("Closure", SHADER_SOCKET_CLOSURE);
+ if(from == SocketType::FLOAT)
+ add_input("value_float", SocketType::FLOAT);
+ else if(from == SocketType::INT)
+ add_input("value_int", SocketType::INT);
+ else if(from == SocketType::COLOR)
+ add_input("value_color", SocketType::COLOR);
+ else if(from == SocketType::VECTOR)
+ add_input("value_vector", SocketType::VECTOR);
+ else if(from == SocketType::POINT)
+ add_input("value_point", SocketType::POINT);
+ else if(from == SocketType::NORMAL)
+ add_input("value_normal", SocketType::NORMAL);
+ else if(from == SocketType::STRING)
+ add_input("value_string", SocketType::STRING);
+ else if(from == SocketType::CLOSURE)
+ add_input("value_closure", SocketType::CLOSURE);
else
assert(0);
- if(to == SHADER_SOCKET_FLOAT)
- add_output("Val", SHADER_SOCKET_FLOAT);
- else if(to == SHADER_SOCKET_INT)
- add_output("ValInt", SHADER_SOCKET_INT);
- else if(to == SHADER_SOCKET_COLOR)
- add_output("Color", SHADER_SOCKET_COLOR);
- else if(to == SHADER_SOCKET_VECTOR)
- add_output("Vector", SHADER_SOCKET_VECTOR);
- else if(to == SHADER_SOCKET_POINT)
- add_output("Point", SHADER_SOCKET_POINT);
- else if(to == SHADER_SOCKET_NORMAL)
- add_output("Normal", SHADER_SOCKET_NORMAL);
- else if(to == SHADER_SOCKET_STRING)
- add_output("String", SHADER_SOCKET_STRING);
- else if(to == SHADER_SOCKET_CLOSURE)
- add_output("Closure", SHADER_SOCKET_CLOSURE);
+ if(to == SocketType::FLOAT)
+ add_output("value_float", SocketType::FLOAT);
+ else if(to == SocketType::INT)
+ add_output("value_int", SocketType::INT);
+ else if(to == SocketType::COLOR)
+ add_output("value_color", SocketType::COLOR);
+ else if(to == SocketType::VECTOR)
+ add_output("value_vector", SocketType::VECTOR);
+ else if(to == SocketType::POINT)
+ add_output("value_point", SocketType::POINT);
+ else if(to == SocketType::NORMAL)
+ add_output("value_normal", SocketType::NORMAL);
+ else if(to == SocketType::STRING)
+ add_output("value_string", SocketType::STRING);
+ else if(to == SocketType::CLOSURE)
+ add_output("value_closure", SocketType::CLOSURE);
else
assert(0);
}
-bool ConvertNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- float3 *optimized_value)
+bool ConvertNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized)
{
ShaderInput *in = inputs[0];
- float3 value = in->value;
+ float3 value = in->value();
/* TODO(DingTo): conversion from/to int is not supported yet, don't fold in that case */
if(in->link == NULL) {
- if(from == SHADER_SOCKET_FLOAT) {
- if(to == SHADER_SOCKET_INT)
- /* float to int */
- return false;
- else
- /* float to float3 */
- *optimized_value = make_float3(value.x, value.x, value.x);
- }
- else if(from == SHADER_SOCKET_INT) {
- if(to == SHADER_SOCKET_FLOAT)
- /* int to float */
- return false;
- else
- /* int to vector/point/normal */
- return false;
- }
- else if(to == SHADER_SOCKET_FLOAT) {
- if(from == SHADER_SOCKET_COLOR)
- /* color to float */
- optimized_value->x = linear_rgb_to_gray(value);
- else
- /* vector/point/normal to float */
- optimized_value->x = average(value);
- }
- else if(to == SHADER_SOCKET_INT) {
- if(from == SHADER_SOCKET_COLOR)
- /* color to int */
- return false;
- else
- /* vector/point/normal to int */
- return false;
+ if(from == SocketType::FLOAT) {
+ if(SocketType::is_float3(to)) {
+ optimized->set(make_float3(value.x, value.x, value.x));
+ return true;
+ }
}
- else {
- *optimized_value = value;
+ else if(SocketType::is_float3(from)) {
+ if(to == SocketType::FLOAT) {
+ if(from == SocketType::COLOR)
+ optimized->set(linear_rgb_to_gray(value));
+ else
+ optimized->set(average(value));
+ return true;
+ }
+ else if(SocketType::is_float3(to)) {
+ optimized->set(value);
+ return true;
+ }
}
-
- return true;
}
return false;
@@ -1650,32 +1662,32 @@ void ConvertNode::compile(SVMCompiler& compiler)
ShaderInput *in = inputs[0];
ShaderOutput *out = outputs[0];
- if(from == SHADER_SOCKET_FLOAT) {
- if(to == SHADER_SOCKET_INT)
+ if(from == SocketType::FLOAT) {
+ if(to == SocketType::INT)
/* float to int */
compiler.add_node(NODE_CONVERT, NODE_CONVERT_FI, compiler.stack_assign(in), compiler.stack_assign(out));
else
/* float to float3 */
compiler.add_node(NODE_CONVERT, NODE_CONVERT_FV, compiler.stack_assign(in), compiler.stack_assign(out));
}
- else if(from == SHADER_SOCKET_INT) {
- if(to == SHADER_SOCKET_FLOAT)
+ else if(from == SocketType::INT) {
+ if(to == SocketType::FLOAT)
/* int to float */
compiler.add_node(NODE_CONVERT, NODE_CONVERT_IF, compiler.stack_assign(in), compiler.stack_assign(out));
else
/* int to vector/point/normal */
compiler.add_node(NODE_CONVERT, NODE_CONVERT_IV, compiler.stack_assign(in), compiler.stack_assign(out));
}
- else if(to == SHADER_SOCKET_FLOAT) {
- if(from == SHADER_SOCKET_COLOR)
+ else if(to == SocketType::FLOAT) {
+ if(from == SocketType::COLOR)
/* color to float */
compiler.add_node(NODE_CONVERT, NODE_CONVERT_CF, compiler.stack_assign(in), compiler.stack_assign(out));
else
/* vector/point/normal to float */
compiler.add_node(NODE_CONVERT, NODE_CONVERT_VF, compiler.stack_assign(in), compiler.stack_assign(out));
}
- else if(to == SHADER_SOCKET_INT) {
- if(from == SHADER_SOCKET_COLOR)
+ else if(to == SocketType::INT) {
+ if(from == SocketType::COLOR)
/* color to int */
compiler.add_node(NODE_CONVERT, NODE_CONVERT_CI, compiler.stack_assign(in), compiler.stack_assign(out));
else
@@ -1691,7 +1703,7 @@ void ConvertNode::compile(SVMCompiler& compiler)
else {
/* set 0,0,0 value */
compiler.add_node(NODE_VALUE_V, compiler.stack_assign(out));
- compiler.add_node(NODE_VALUE_V, in->value);
+ compiler.add_node(NODE_VALUE_V, in->value());
}
}
}
@@ -1701,17 +1713,17 @@ void ConvertNode::compile(OSLCompiler& compiler)
/* constant folding should eliminate proxy nodes */
assert(from != to);
- if(from == SHADER_SOCKET_FLOAT)
+ if(from == SocketType::FLOAT)
compiler.add(this, "node_convert_from_float");
- else if(from == SHADER_SOCKET_INT)
+ else if(from == SocketType::INT)
compiler.add(this, "node_convert_from_int");
- else if(from == SHADER_SOCKET_COLOR)
+ else if(from == SocketType::COLOR)
compiler.add(this, "node_convert_from_color");
- else if(from == SHADER_SOCKET_VECTOR)
+ else if(from == SocketType::VECTOR)
compiler.add(this, "node_convert_from_vector");
- else if(from == SHADER_SOCKET_POINT)
+ else if(from == SocketType::POINT)
compiler.add(this, "node_convert_from_point");
- else if(from == SHADER_SOCKET_NORMAL)
+ else if(from == SocketType::NORMAL)
compiler.add(this, "node_convert_from_normal");
else
assert(0);
@@ -1724,17 +1736,17 @@ BsdfNode::BsdfNode(bool scattering_)
{
special_type = SHADER_SPECIAL_TYPE_CLOSURE;
- add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
+ add_input("Color", SocketType::COLOR, make_float3(0.8f, 0.8f, 0.8f));
+ add_input("Normal", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ add_input("SurfaceMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL);
if(scattering) {
closure = CLOSURE_BSSRDF_CUBIC_ID;
- add_output("BSSRDF", SHADER_SOCKET_CLOSURE);
+ add_output("BSSRDF", SocketType::CLOSURE);
}
else {
closure = CLOSURE_BSDF_DIFFUSE_ID;
- add_output("BSDF", SHADER_SOCKET_CLOSURE);
+ add_output("BSDF", SocketType::CLOSURE);
}
}
@@ -1747,7 +1759,7 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
if(color_in->link)
compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value);
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value());
int normal_offset = compiler.stack_assign_if_linked(normal_in);
int tangent_offset = (tangent_in) ? compiler.stack_assign_if_linked(tangent_in) : SVM_STACK_INVALID;
@@ -1759,8 +1771,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
(param1)? compiler.stack_assign(param1): SVM_STACK_INVALID,
(param2)? compiler.stack_assign(param2): SVM_STACK_INVALID,
compiler.closure_mix_weight_offset()),
- __float_as_int((param1)? param1->value.x: 0.0f),
- __float_as_int((param2)? param2->value.x: 0.0f));
+ __float_as_int((param1)? param1->value_float(): 0.0f),
+ __float_as_int((param2)? param2->value_float(): 0.0f));
compiler.add_node(normal_offset, tangent_offset, param3_offset, param4_offset);
}
@@ -1777,9 +1789,9 @@ void BsdfNode::compile(OSLCompiler& /*compiler*/)
/* Anisotropic BSDF Closure */
-static ShaderEnum aniso_distribution_init()
+static NodeEnum aniso_distribution_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID);
enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
@@ -1788,18 +1800,18 @@ static ShaderEnum aniso_distribution_init()
return enm;
}
-ShaderEnum AnisotropicBsdfNode::distribution_enum = aniso_distribution_init();
+NodeEnum AnisotropicBsdfNode::distribution_enum = aniso_distribution_init();
AnisotropicBsdfNode::AnisotropicBsdfNode()
{
closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
- distribution = ustring("GGX");
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
- add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT);
+ add_input("Tangent", SocketType::VECTOR, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f);
- add_input("Anisotropy", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Rotation", SHADER_SOCKET_FLOAT, 0.0f);
+ add_input("Roughness", SocketType::FLOAT, 0.2f);
+ add_input("Anisotropy", SocketType::FLOAT, 0.5f);
+ add_input("Rotation", SocketType::FLOAT, 0.0f);
}
void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -1816,22 +1828,22 @@ void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attrib
void AnisotropicBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation"));
}
void AnisotropicBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("distribution", distribution);
+ compiler.parameter("distribution", distribution_enum[distribution]);
compiler.add(this, "node_anisotropic_bsdf");
}
/* Glossy BSDF Closure */
-static ShaderEnum glossy_distribution_init()
+static NodeEnum glossy_distribution_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Sharp", CLOSURE_BSDF_REFLECTION_ID);
enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
@@ -1841,20 +1853,20 @@ static ShaderEnum glossy_distribution_init()
return enm;
}
-ShaderEnum GlossyBsdfNode::distribution_enum = glossy_distribution_init();
+NodeEnum GlossyBsdfNode::distribution_enum = glossy_distribution_init();
GlossyBsdfNode::GlossyBsdfNode()
{
closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
- distribution = ustring("GGX");
- distribution_orig = ustring("");
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f);
+ add_input("Roughness", SocketType::FLOAT, 0.2f);
}
void GlossyBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == "") {
+ if(distribution_orig == NBUILTIN_CLOSURES) {
distribution_orig = distribution;
}
Integrator *integrator = scene->integrator;
@@ -1863,26 +1875,26 @@ void GlossyBsdfNode::simplify_settings(Scene *scene)
* Note: Keep the epsilon in sync with kernel!
*/
ShaderInput *roughness_input = input("Roughness");
- if(!roughness_input->link && roughness_input->value.x <= 1e-4f) {
- distribution = ustring("Sharp");
+ if(!roughness_input->link && roughness_input->value_float() <= 1e-4f) {
+ distribution = CLOSURE_BSDF_REFLECTION_ID;
}
}
else {
/* Rollback to original distribution when filter glossy is used. */
distribution = distribution_orig;
}
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
}
bool GlossyBsdfNode::has_integrator_dependency()
{
ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness_input->value.x <= 1e-4f;
+ return !roughness_input->link && roughness_input->value_float() <= 1e-4f;
}
void GlossyBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
if(closure == CLOSURE_BSDF_REFLECTION_ID)
BsdfNode::compile(compiler, NULL, NULL);
@@ -1892,15 +1904,15 @@ void GlossyBsdfNode::compile(SVMCompiler& compiler)
void GlossyBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("distribution", distribution);
+ compiler.parameter("distribution", distribution_enum[distribution]);
compiler.add(this, "node_glossy_bsdf");
}
/* Glass BSDF Closure */
-static ShaderEnum glass_distribution_init()
+static NodeEnum glass_distribution_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
@@ -1909,21 +1921,21 @@ static ShaderEnum glass_distribution_init()
return enm;
}
-ShaderEnum GlassBsdfNode::distribution_enum = glass_distribution_init();
+NodeEnum GlassBsdfNode::distribution_enum = glass_distribution_init();
GlassBsdfNode::GlassBsdfNode()
{
closure = CLOSURE_BSDF_SHARP_GLASS_ID;
- distribution = ustring("Sharp");
- distribution_orig = ustring("");
+ distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f);
+ add_input("Roughness", SocketType::FLOAT, 0.0f);
+ add_input("IOR", SocketType::FLOAT, 0.3f);
}
void GlassBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == "") {
+ if(distribution_orig == NBUILTIN_CLOSURES) {
distribution_orig = distribution;
}
Integrator *integrator = scene->integrator;
@@ -1932,26 +1944,26 @@ void GlassBsdfNode::simplify_settings(Scene *scene)
* Note: Keep the epsilon in sync with kernel!
*/
ShaderInput *roughness_input = input("Roughness");
- if(!roughness_input->link && roughness_input->value.x <= 1e-4f) {
- distribution = ustring("Sharp");
+ if(!roughness_input->link && roughness_input->value_float() <= 1e-4f) {
+ distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
}
}
else {
/* Rollback to original distribution when filter glossy is used. */
distribution = distribution_orig;
}
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
}
bool GlassBsdfNode::has_integrator_dependency()
{
ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness_input->value.x <= 1e-4f;
+ return !roughness_input->link && roughness_input->value_float() <= 1e-4f;
}
void GlassBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
if(closure == CLOSURE_BSDF_SHARP_GLASS_ID)
BsdfNode::compile(compiler, NULL, input("IOR"));
@@ -1961,15 +1973,15 @@ void GlassBsdfNode::compile(SVMCompiler& compiler)
void GlassBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("distribution", distribution);
+ compiler.parameter("distribution", distribution_enum[distribution]);
compiler.add(this, "node_glass_bsdf");
}
/* Refraction BSDF Closure */
-static ShaderEnum refraction_distribution_init()
+static NodeEnum refraction_distribution_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID);
enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
@@ -1978,21 +1990,21 @@ static ShaderEnum refraction_distribution_init()
return enm;
}
-ShaderEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init();
+NodeEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init();
RefractionBsdfNode::RefractionBsdfNode()
{
closure = CLOSURE_BSDF_REFRACTION_ID;
- distribution = ustring("Sharp");
- distribution_orig = ustring("");
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ distribution_orig = NBUILTIN_CLOSURES;
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f);
+ add_input("Roughness", SocketType::FLOAT, 0.0f);
+ add_input("IOR", SocketType::FLOAT, 0.3f);
}
void RefractionBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == "") {
+ if(distribution_orig == NBUILTIN_CLOSURES) {
distribution_orig = distribution;
}
Integrator *integrator = scene->integrator;
@@ -2001,26 +2013,26 @@ void RefractionBsdfNode::simplify_settings(Scene *scene)
* Note: Keep the epsilon in sync with kernel!
*/
ShaderInput *roughness_input = input("Roughness");
- if(!roughness_input->link && roughness_input->value.x <= 1e-4f) {
- distribution = ustring("Sharp");
+ if(!roughness_input->link && roughness_input->value_float() <= 1e-4f) {
+ distribution = CLOSURE_BSDF_REFRACTION_ID;
}
}
else {
/* Rollback to original distribution when filter glossy is used. */
distribution = distribution_orig;
}
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
}
bool RefractionBsdfNode::has_integrator_dependency()
{
ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness_input->value.x <= 1e-4f;
+ return !roughness_input->link && roughness_input->value_float() <= 1e-4f;
}
void RefractionBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
if(closure == CLOSURE_BSDF_REFRACTION_ID)
BsdfNode::compile(compiler, NULL, input("IOR"));
@@ -2030,15 +2042,15 @@ void RefractionBsdfNode::compile(SVMCompiler& compiler)
void RefractionBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("distribution", distribution);
+ compiler.parameter("distribution", distribution_enum[distribution]);
compiler.add(this, "node_refraction_bsdf");
}
/* Toon BSDF Closure */
-static ShaderEnum toon_component_init()
+static NodeEnum toon_component_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Diffuse", CLOSURE_BSDF_DIFFUSE_TOON_ID);
enm.insert("Glossy", CLOSURE_BSDF_GLOSSY_TOON_ID);
@@ -2046,27 +2058,27 @@ static ShaderEnum toon_component_init()
return enm;
}
-ShaderEnum ToonBsdfNode::component_enum = toon_component_init();
+NodeEnum ToonBsdfNode::component_enum = toon_component_init();
ToonBsdfNode::ToonBsdfNode()
{
closure = CLOSURE_BSDF_DIFFUSE_TOON_ID;
- component = ustring("Diffuse");
+ component = CLOSURE_BSDF_DIFFUSE_TOON_ID;
- add_input("Size", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Smooth", SHADER_SOCKET_FLOAT, 0.0f);
+ add_input("Size", SocketType::FLOAT, 0.5f);
+ add_input("Smooth", SocketType::FLOAT, 0.0f);
}
void ToonBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)component_enum[component];
+ closure = component;
BsdfNode::compile(compiler, input("Size"), input("Smooth"));
}
void ToonBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("component", component);
+ compiler.parameter("component", component_enum[component]);
compiler.add(this, "node_toon_bsdf");
}
@@ -2076,7 +2088,7 @@ VelvetBsdfNode::VelvetBsdfNode()
{
closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
- add_input("Sigma", SHADER_SOCKET_FLOAT, 1.0f);
+ add_input("Sigma", SocketType::FLOAT, 1.0f);
}
void VelvetBsdfNode::compile(SVMCompiler& compiler)
@@ -2094,7 +2106,7 @@ void VelvetBsdfNode::compile(OSLCompiler& compiler)
DiffuseBsdfNode::DiffuseBsdfNode()
{
closure = CLOSURE_BSDF_DIFFUSE_ID;
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
+ add_input("Roughness", SocketType::FLOAT, 0.0f);
}
void DiffuseBsdfNode::compile(SVMCompiler& compiler)
@@ -2144,9 +2156,9 @@ void TransparentBsdfNode::compile(OSLCompiler& compiler)
/* Subsurface Scattering Closure */
-static ShaderEnum subsurface_falloff_init()
+static NodeEnum subsurface_falloff_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Cubic", CLOSURE_BSSRDF_CUBIC_ID);
enm.insert("Gaussian", CLOSURE_BSSRDF_GAUSSIAN_ID);
@@ -2155,28 +2167,29 @@ static ShaderEnum subsurface_falloff_init()
return enm;
}
-ShaderEnum SubsurfaceScatteringNode::falloff_enum = subsurface_falloff_init();
+NodeEnum SubsurfaceScatteringNode::falloff_enum = subsurface_falloff_init();
SubsurfaceScatteringNode::SubsurfaceScatteringNode()
: BsdfNode(true)
{
name = "subsurface_scattering";
- closure = CLOSURE_BSSRDF_CUBIC_ID;
+ falloff = CLOSURE_BSSRDF_CUBIC_ID;
- add_input("Scale", SHADER_SOCKET_FLOAT, 0.01f);
- add_input("Radius", SHADER_SOCKET_VECTOR, make_float3(0.1f, 0.1f, 0.1f));
- add_input("Sharpness", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Texture Blur", SHADER_SOCKET_FLOAT, 1.0f);
+ add_input("Scale", SocketType::FLOAT, 0.01f);
+ add_input("Radius", SocketType::VECTOR, make_float3(0.1f, 0.1f, 0.1f));
+ add_input("Sharpness", SocketType::FLOAT, 0.0f);
+ add_input("Texture Blur", SocketType::FLOAT, 1.0f);
}
void SubsurfaceScatteringNode::compile(SVMCompiler& compiler)
{
+ closure = falloff;
BsdfNode::compile(compiler, input("Scale"), input("Texture Blur"), input("Radius"), input("Sharpness"));
}
void SubsurfaceScatteringNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("Falloff", falloff_enum[closure]);
+ compiler.parameter("falloff", falloff_enum[closure]);
compiler.add(this, "node_subsurface_scattering");
}
@@ -2192,11 +2205,11 @@ bool SubsurfaceScatteringNode::has_bssrdf_bump()
EmissionNode::EmissionNode()
: ShaderNode("emission")
{
- add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("Strength", SHADER_SOCKET_FLOAT, 10.0f);
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
+ add_input("Color", SocketType::COLOR, make_float3(0.8f, 0.8f, 0.8f));
+ add_input("Strength", SocketType::FLOAT, 10.0f);
+ add_input("SurfaceMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL);
- add_output("Emission", SHADER_SOCKET_CLOSURE);
+ add_output("Emission", SocketType::CLOSURE);
}
void EmissionNode::compile(SVMCompiler& compiler)
@@ -2210,7 +2223,7 @@ void EmissionNode::compile(SVMCompiler& compiler)
compiler.stack_assign(strength_in));
}
else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value * strength_in->value.x);
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value() * strength_in->value_float());
compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
}
@@ -2220,13 +2233,13 @@ void EmissionNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_emission");
}
-bool EmissionNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 * /*optimized_value*/)
+bool EmissionNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *)
{
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
- return ((!color_in->link && color_in->value == make_float3(0.0f, 0.0f, 0.0f)) ||
- (!strength_in->link && strength_in->value.x == 0.0f));
+ return ((!color_in->link && color_in->value() == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!strength_in->link && strength_in->value_float() == 0.0f));
}
/* Background Closure */
@@ -2234,11 +2247,11 @@ bool EmissionNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socke
BackgroundNode::BackgroundNode()
: ShaderNode("background")
{
- add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
+ add_input("Color", SocketType::COLOR, make_float3(0.8f, 0.8f, 0.8f));
+ add_input("Strength", SocketType::FLOAT, 1.0f);
+ add_input("SurfaceMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL);
- add_output("Background", SHADER_SOCKET_CLOSURE);
+ add_output("Background", SocketType::CLOSURE);
}
void BackgroundNode::compile(SVMCompiler& compiler)
@@ -2252,7 +2265,7 @@ void BackgroundNode::compile(SVMCompiler& compiler)
compiler.stack_assign(strength_in));
}
else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value*strength_in->value.x);
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value()*strength_in->value_float());
compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset());
}
@@ -2262,13 +2275,13 @@ void BackgroundNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_background");
}
-bool BackgroundNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 * /*optimized_value*/)
+bool BackgroundNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *)
{
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
- return ((!color_in->link && color_in->value == make_float3(0.0f, 0.0f, 0.0f)) ||
- (!strength_in->link && strength_in->value.x == 0.0f));
+ return ((!color_in->link && color_in->value() == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!strength_in->link && strength_in->value_float() == 0.0f));
}
/* Holdout Closure */
@@ -2276,10 +2289,10 @@ bool BackgroundNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*soc
HoldoutNode::HoldoutNode()
: ShaderNode("holdout")
{
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
- add_input("VolumeMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
+ add_input("SurfaceMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL);
+ add_input("VolumeMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL);
- add_output("Holdout", SHADER_SOCKET_CLOSURE);
+ add_output("Holdout", SocketType::CLOSURE);
}
void HoldoutNode::compile(SVMCompiler& compiler)
@@ -2300,11 +2313,11 @@ void HoldoutNode::compile(OSLCompiler& compiler)
AmbientOcclusionNode::AmbientOcclusionNode()
: ShaderNode("ambient_occlusion")
{
- add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
+ add_input("NormalIn", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ add_input("Color", SocketType::COLOR, make_float3(0.8f, 0.8f, 0.8f));
+ add_input("SurfaceMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL);
- add_output("AO", SHADER_SOCKET_CLOSURE);
+ add_output("AO", SocketType::CLOSURE);
}
void AmbientOcclusionNode::compile(SVMCompiler& compiler)
@@ -2314,7 +2327,7 @@ void AmbientOcclusionNode::compile(SVMCompiler& compiler)
if(color_in->link)
compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value);
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value());
compiler.add_node(NODE_CLOSURE_AMBIENT_OCCLUSION, compiler.closure_mix_weight_offset());
}
@@ -2331,11 +2344,11 @@ VolumeNode::VolumeNode()
{
closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
- add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("Density", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("VolumeMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
+ add_input("Color", SocketType::COLOR, make_float3(0.8f, 0.8f, 0.8f));
+ add_input("Density", SocketType::FLOAT, 1.0f);
+ add_input("VolumeMixWeight", SocketType::FLOAT, 0.0f, SocketType::SVM_INTERNAL);
- add_output("Volume", SHADER_SOCKET_CLOSURE);
+ add_output("Volume", SocketType::CLOSURE);
}
void VolumeNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2)
@@ -2345,15 +2358,15 @@ void VolumeNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput
if(color_in->link)
compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value);
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value());
compiler.add_node(NODE_CLOSURE_VOLUME,
compiler.encode_uchar4(closure,
(param1)? compiler.stack_assign(param1): SVM_STACK_INVALID,
(param2)? compiler.stack_assign(param2): SVM_STACK_INVALID,
compiler.closure_mix_weight_offset()),
- __float_as_int((param1)? param1->value.x: 0.0f),
- __float_as_int((param2)? param2->value.x: 0.0f));
+ __float_as_int((param1)? param1->value_float(): 0.0f),
+ __float_as_int((param2)? param2->value_float(): 0.0f));
}
void VolumeNode::compile(SVMCompiler& compiler)
@@ -2389,7 +2402,7 @@ ScatterVolumeNode::ScatterVolumeNode()
{
closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
- add_input("Anisotropy", SHADER_SOCKET_FLOAT, 0.0f);
+ add_input("Anisotropy", SocketType::FLOAT, 0.0f);
}
void ScatterVolumeNode::compile(SVMCompiler& compiler)
@@ -2404,9 +2417,9 @@ void ScatterVolumeNode::compile(OSLCompiler& compiler)
/* Hair BSDF Closure */
-static ShaderEnum hair_component_init()
+static NodeEnum hair_component_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID);
enm.insert("Transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID);
@@ -2414,29 +2427,29 @@ static ShaderEnum hair_component_init()
return enm;
}
-ShaderEnum HairBsdfNode::component_enum = hair_component_init();
+NodeEnum HairBsdfNode::component_enum = hair_component_init();
HairBsdfNode::HairBsdfNode()
{
closure = CLOSURE_BSDF_HAIR_REFLECTION_ID;
- component = ustring("Reflection");
+ component = CLOSURE_BSDF_HAIR_REFLECTION_ID;
- add_input("Offset", SHADER_SOCKET_FLOAT);
- add_input("RoughnessU", SHADER_SOCKET_FLOAT);
- add_input("RoughnessV", SHADER_SOCKET_FLOAT);
- add_input("Tangent", SHADER_SOCKET_VECTOR);
+ add_input("Offset", SocketType::FLOAT);
+ add_input("RoughnessU", SocketType::FLOAT);
+ add_input("RoughnessV", SocketType::FLOAT);
+ add_input("Tangent", SocketType::VECTOR);
}
void HairBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)component_enum[component];
+ closure = component;
BsdfNode::compile(compiler, input("RoughnessU"), input("RoughnessV"), input("Offset"));
}
void HairBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("component", component);
+ compiler.parameter("component", component_enum[component]);
compiler.add(this, "node_hair_bsdf");
}
@@ -2448,15 +2461,15 @@ GeometryNode::GeometryNode()
{
special_type = SHADER_SPECIAL_TYPE_GEOMETRY;
- add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_output("Position", SHADER_SOCKET_POINT);
- add_output("Normal", SHADER_SOCKET_NORMAL);
- add_output("Tangent", SHADER_SOCKET_NORMAL);
- add_output("True Normal", SHADER_SOCKET_NORMAL);
- add_output("Incoming", SHADER_SOCKET_VECTOR);
- add_output("Parametric", SHADER_SOCKET_POINT);
- add_output("Backfacing", SHADER_SOCKET_FLOAT);
- add_output("Pointiness", SHADER_SOCKET_FLOAT);
+ add_input("NormalIn", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ add_output("Position", SocketType::POINT);
+ add_output("Normal", SocketType::NORMAL);
+ add_output("Tangent", SocketType::NORMAL);
+ add_output("True Normal", SocketType::NORMAL);
+ add_output("Incoming", SocketType::VECTOR);
+ add_output("Parametric", SocketType::POINT);
+ add_output("Backfacing", SocketType::FLOAT);
+ add_output("Pointiness", SocketType::FLOAT);
}
void GeometryNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -2554,14 +2567,14 @@ void GeometryNode::compile(OSLCompiler& compiler)
TextureCoordinateNode::TextureCoordinateNode()
: ShaderNode("texture_coordinate")
{
- add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- 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);
- add_output("Window", SHADER_SOCKET_POINT);
- add_output("Reflection", SHADER_SOCKET_NORMAL);
+ add_input("NormalIn", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ add_output("Generated", SocketType::POINT);
+ add_output("Normal", SocketType::NORMAL);
+ add_output("UV", SocketType::POINT);
+ add_output("Object", SocketType::POINT);
+ add_output("Camera", SocketType::POINT);
+ add_output("Window", SocketType::POINT);
+ add_output("Reflection", SocketType::NORMAL);
from_dupli = false;
use_transform = false;
@@ -2704,7 +2717,7 @@ UVMapNode::UVMapNode()
attribute = "";
from_dupli = false;
- add_output("UV", SHADER_SOCKET_POINT);
+ add_output("UV", SocketType::POINT);
}
void UVMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -2773,18 +2786,18 @@ void UVMapNode::compile(OSLCompiler& compiler)
LightPathNode::LightPathNode()
: ShaderNode("light_path")
{
- add_output("Is Camera Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Shadow Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Diffuse Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Glossy Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Singular Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Reflection Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Transmission Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Volume Scatter Ray", SHADER_SOCKET_FLOAT);
- add_output("Ray Length", SHADER_SOCKET_FLOAT);
- add_output("Ray Depth", SHADER_SOCKET_FLOAT);
- add_output("Transparent Depth", SHADER_SOCKET_FLOAT);
- add_output("Transmission Depth", SHADER_SOCKET_FLOAT);
+ add_output("Is Camera Ray", SocketType::FLOAT);
+ add_output("Is Shadow Ray", SocketType::FLOAT);
+ add_output("Is Diffuse Ray", SocketType::FLOAT);
+ add_output("Is Glossy Ray", SocketType::FLOAT);
+ add_output("Is Singular Ray", SocketType::FLOAT);
+ add_output("Is Reflection Ray", SocketType::FLOAT);
+ add_output("Is Transmission Ray", SocketType::FLOAT);
+ add_output("Is Volume Scatter Ray", SocketType::FLOAT);
+ add_output("Ray Length", SocketType::FLOAT);
+ add_output("Ray Depth", SocketType::FLOAT);
+ add_output("Transparent Depth", SocketType::FLOAT);
+ add_output("Transmission Depth", SocketType::FLOAT);
}
void LightPathNode::compile(SVMCompiler& compiler)
@@ -2863,11 +2876,11 @@ void LightPathNode::compile(OSLCompiler& compiler)
LightFalloffNode::LightFalloffNode()
: ShaderNode("light_fallof")
{
- add_input("Strength", SHADER_SOCKET_FLOAT, 100.0f);
- add_input("Smooth", SHADER_SOCKET_FLOAT, 0.0f);
- add_output("Quadratic", SHADER_SOCKET_FLOAT);
- add_output("Linear", SHADER_SOCKET_FLOAT);
- add_output("Constant", SHADER_SOCKET_FLOAT);
+ add_input("Strength", SocketType::FLOAT, 100.0f);
+ add_input("Smooth", SocketType::FLOAT, 0.0f);
+ add_output("Quadratic", SocketType::FLOAT);
+ add_output("Linear", SocketType::FLOAT);
+ add_output("Constant", SocketType::FLOAT);
}
void LightFalloffNode::compile(SVMCompiler& compiler)
@@ -2913,10 +2926,10 @@ void LightFalloffNode::compile(OSLCompiler& compiler)
ObjectInfoNode::ObjectInfoNode()
: ShaderNode("object_info")
{
- add_output("Location", SHADER_SOCKET_VECTOR);
- add_output("Object Index", SHADER_SOCKET_FLOAT);
- add_output("Material Index", SHADER_SOCKET_FLOAT);
- add_output("Random", SHADER_SOCKET_FLOAT);
+ add_output("Location", SocketType::VECTOR);
+ add_output("Object Index", SocketType::FLOAT);
+ add_output("Material Index", SocketType::FLOAT);
+ add_output("Random", SocketType::FLOAT);
}
void ObjectInfoNode::compile(SVMCompiler& compiler)
@@ -2952,16 +2965,16 @@ void ObjectInfoNode::compile(OSLCompiler& compiler)
ParticleInfoNode::ParticleInfoNode()
: ShaderNode("particle_info")
{
- add_output("Index", SHADER_SOCKET_FLOAT);
- add_output("Age", SHADER_SOCKET_FLOAT);
- add_output("Lifetime", SHADER_SOCKET_FLOAT);
- add_output("Location", SHADER_SOCKET_POINT);
+ add_output("Index", SocketType::FLOAT);
+ add_output("Age", SocketType::FLOAT);
+ add_output("Lifetime", SocketType::FLOAT);
+ add_output("Location", SocketType::POINT);
#if 0 /* not yet supported */
add_output("Rotation", SHADER_SOCKET_QUATERNION);
#endif
- add_output("Size", SHADER_SOCKET_FLOAT);
- add_output("Velocity", SHADER_SOCKET_VECTOR);
- add_output("Angular Velocity", SHADER_SOCKET_VECTOR);
+ add_output("Size", SocketType::FLOAT);
+ add_output("Velocity", SocketType::VECTOR);
+ add_output("Angular Velocity", SocketType::VECTOR);
}
void ParticleInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -3046,12 +3059,12 @@ void ParticleInfoNode::compile(OSLCompiler& compiler)
HairInfoNode::HairInfoNode()
: ShaderNode("hair_info")
{
- add_output("Is Strand", SHADER_SOCKET_FLOAT);
- add_output("Intercept", SHADER_SOCKET_FLOAT);
- add_output("Thickness", SHADER_SOCKET_FLOAT);
- add_output("Tangent Normal", SHADER_SOCKET_NORMAL);
+ add_output("Is Strand", SocketType::FLOAT);
+ add_output("Intercept", SocketType::FLOAT);
+ add_output("Thickness", SocketType::FLOAT);
+ add_output("Tangent Normal", SocketType::NORMAL);
/*output for minimum hair width transparency - deactivated*/
- /*add_output("Fade", SHADER_SOCKET_FLOAT);*/
+ /*add_output("Fade", SocketType::FLOAT);*/
}
void HairInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -3110,13 +3123,12 @@ ValueNode::ValueNode()
{
value = 0.0f;
- add_output("Value", SHADER_SOCKET_FLOAT);
+ add_output("Value", SocketType::FLOAT);
}
-bool ValueNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/,
- float3 *optimized_value)
+bool ValueNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized)
{
- *optimized_value = make_float3(value, value, value);
+ optimized->set(value);
return true;
}
@@ -3140,13 +3152,12 @@ ColorNode::ColorNode()
{
value = make_float3(0.0f, 0.0f, 0.0f);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_output("Color", SocketType::COLOR);
}
-bool ColorNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/,
- float3 *optimized_value)
+bool ColorNode::constant_fold(ShaderGraph *, ShaderOutput *, ShaderInput *optimized)
{
- *optimized_value = value;
+ optimized->set(value);
return true;
}
@@ -3174,9 +3185,9 @@ AddClosureNode::AddClosureNode()
{
special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
- add_input("Closure1", SHADER_SOCKET_CLOSURE);
- add_input("Closure2", SHADER_SOCKET_CLOSURE);
- add_output("Closure", SHADER_SOCKET_CLOSURE);
+ add_input("Closure1", SocketType::CLOSURE);
+ add_input("Closure2", SocketType::CLOSURE);
+ add_output("Closure", SocketType::CLOSURE);
}
void AddClosureNode::compile(SVMCompiler& /*compiler*/)
@@ -3196,10 +3207,10 @@ MixClosureNode::MixClosureNode()
{
special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
- add_input("Fac", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Closure1", SHADER_SOCKET_CLOSURE);
- add_input("Closure2", SHADER_SOCKET_CLOSURE);
- add_output("Closure", SHADER_SOCKET_CLOSURE);
+ add_input("Fac", SocketType::FLOAT, 0.5f);
+ add_input("Closure1", SocketType::CLOSURE);
+ add_input("Closure2", SocketType::CLOSURE);
+ add_output("Closure", SocketType::CLOSURE);
}
void MixClosureNode::compile(SVMCompiler& /*compiler*/)
@@ -3212,7 +3223,7 @@ void MixClosureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_mix_closure");
}
-bool MixClosureNode::constant_fold(ShaderGraph *graph, ShaderOutput * /*socket*/, float3 * /*optimized_value*/)
+bool MixClosureNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *)
{
ShaderInput *fac_in = input("Fac");
ShaderInput *closure1_in = input("Closure1");
@@ -3229,12 +3240,12 @@ bool MixClosureNode::constant_fold(ShaderGraph *graph, ShaderOutput * /*socket*/
/* check for closure links and make sure factor link is disconnected */
if(closure1_in->link && closure2_in->link && !fac_in->link) {
/* factor 0.0 */
- if(fac_in->value.x == 0.0f) {
+ if(fac_in->value_float() == 0.0f) {
graph->relink(this, closure_out, closure1_in->link);
return true;
}
/* factor 1.0 */
- else if(fac_in->value.x == 1.0f) {
+ else if(fac_in->value_float() == 1.0f) {
graph->relink(this, closure_out, closure2_in->link);
return true;
}
@@ -3248,10 +3259,10 @@ bool MixClosureNode::constant_fold(ShaderGraph *graph, ShaderOutput * /*socket*/
MixClosureWeightNode::MixClosureWeightNode()
: ShaderNode("mix_closure_weight")
{
- add_input("Weight", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Fac", SHADER_SOCKET_FLOAT, 1.0f);
- add_output("Weight1", SHADER_SOCKET_FLOAT);
- add_output("Weight2", SHADER_SOCKET_FLOAT);
+ add_input("Weight", SocketType::FLOAT, 1.0f);
+ add_input("Fac", SocketType::FLOAT, 1.0f);
+ add_output("Weight1", SocketType::FLOAT);
+ add_output("Weight2", SocketType::FLOAT);
}
void MixClosureWeightNode::compile(SVMCompiler& compiler)
@@ -3279,9 +3290,9 @@ void MixClosureWeightNode::compile(OSLCompiler& /*compiler*/)
InvertNode::InvertNode()
: ShaderNode("invert")
{
- add_input("Fac", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Color", SHADER_SOCKET_COLOR);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("Fac", SocketType::FLOAT, 1.0f);
+ add_input("Color", SocketType::COLOR);
+ add_output("Color", SocketType::COLOR);
}
void InvertNode::compile(SVMCompiler& compiler)
@@ -3306,19 +3317,19 @@ void InvertNode::compile(OSLCompiler& compiler)
MixNode::MixNode()
: ShaderNode("mix")
{
- type = ustring("Mix");
+ type = NODE_MIX_BLEND;
use_clamp = false;
- add_input("Fac", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Color1", SHADER_SOCKET_COLOR);
- add_input("Color2", SHADER_SOCKET_COLOR);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("Fac", SocketType::FLOAT, 0.5f);
+ add_input("Color1", SocketType::COLOR);
+ add_input("Color2", SocketType::COLOR);
+ add_output("Color", SocketType::COLOR);
}
-static ShaderEnum mix_type_init()
+static NodeEnum mix_type_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Mix", NODE_MIX_BLEND);
enm.insert("Add", NODE_MIX_ADD);
@@ -3342,7 +3353,7 @@ static ShaderEnum mix_type_init()
return enm;
}
-ShaderEnum MixNode::type_enum = mix_type_init();
+NodeEnum MixNode::type_enum = mix_type_init();
void MixNode::compile(SVMCompiler& compiler)
{
@@ -3355,7 +3366,7 @@ void MixNode::compile(SVMCompiler& compiler)
compiler.stack_assign(fac_in),
compiler.stack_assign(color1_in),
compiler.stack_assign(color2_in));
- compiler.add_node(NODE_MIX, type_enum[type], compiler.stack_assign(color_out));
+ compiler.add_node(NODE_MIX, type, compiler.stack_assign(color_out));
if(use_clamp) {
compiler.add_node(NODE_MIX, 0, compiler.stack_assign(color_out));
@@ -3365,12 +3376,12 @@ void MixNode::compile(SVMCompiler& compiler)
void MixNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("type", type);
- compiler.parameter("Clamp", use_clamp);
+ compiler.parameter("type", type_enum[type]);
+ compiler.parameter("use_clamp", use_clamp);
compiler.add(this, "node_mix");
}
-bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput * /*socket*/, float3 * optimized_value)
+bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *optimized)
{
if(type != ustring("Mix")) {
return false;
@@ -3390,19 +3401,19 @@ bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput * /*socket*/, float
/* remove unused mix color input when factor is 0.0 or 1.0 */
if(!fac_in->link) {
/* factor 0.0 */
- if(fac_in->value.x == 0.0f) {
+ if(fac_in->value_float() == 0.0f) {
if(color1_in->link)
graph->relink(this, color_out, color1_in->link);
else
- *optimized_value = color1_in->value;
+ optimized->set(color1_in->value());
return true;
}
/* factor 1.0 */
- else if(fac_in->value.x == 1.0f) {
+ else if(fac_in->value_float() == 1.0f) {
if(color2_in->link)
graph->relink(this, color_out, color2_in->link);
else
- *optimized_value = color2_in->value;
+ optimized->set(color2_in->value());
return true;
}
}
@@ -3414,10 +3425,10 @@ bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput * /*socket*/, float
CombineRGBNode::CombineRGBNode()
: ShaderNode("combine_rgb")
{
- add_input("R", SHADER_SOCKET_FLOAT);
- add_input("G", SHADER_SOCKET_FLOAT);
- add_input("B", SHADER_SOCKET_FLOAT);
- add_output("Image", SHADER_SOCKET_COLOR);
+ add_input("R", SocketType::FLOAT);
+ add_input("G", SocketType::FLOAT);
+ add_input("B", SocketType::FLOAT);
+ add_output("Image", SocketType::COLOR);
}
void CombineRGBNode::compile(SVMCompiler& compiler)
@@ -3449,10 +3460,10 @@ void CombineRGBNode::compile(OSLCompiler& compiler)
CombineXYZNode::CombineXYZNode()
: ShaderNode("combine_xyz")
{
- add_input("X", SHADER_SOCKET_FLOAT);
- add_input("Y", SHADER_SOCKET_FLOAT);
- add_input("Z", SHADER_SOCKET_FLOAT);
- add_output("Vector", SHADER_SOCKET_VECTOR);
+ add_input("X", SocketType::FLOAT);
+ add_input("Y", SocketType::FLOAT);
+ add_input("Z", SocketType::FLOAT);
+ add_output("Vector", SocketType::VECTOR);
}
void CombineXYZNode::compile(SVMCompiler& compiler)
@@ -3484,10 +3495,10 @@ void CombineXYZNode::compile(OSLCompiler& compiler)
CombineHSVNode::CombineHSVNode()
: ShaderNode("combine_hsv")
{
- add_input("H", SHADER_SOCKET_FLOAT);
- add_input("S", SHADER_SOCKET_FLOAT);
- add_input("V", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("H", SocketType::FLOAT);
+ add_input("S", SocketType::FLOAT);
+ add_input("V", SocketType::FLOAT);
+ add_output("Color", SocketType::COLOR);
}
void CombineHSVNode::compile(SVMCompiler& compiler)
@@ -3514,20 +3525,20 @@ void CombineHSVNode::compile(OSLCompiler& compiler)
GammaNode::GammaNode()
: ShaderNode("gamma")
{
- add_input("Color", SHADER_SOCKET_COLOR);
- add_input("Gamma", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("Color", SocketType::COLOR);
+ add_input("Gamma", SocketType::FLOAT);
+ add_output("Color", SocketType::COLOR);
}
-bool GammaNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value)
+bool GammaNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized)
{
ShaderInput *color_in = input("Color");
ShaderInput *gamma_in = input("Gamma");
if(socket == output("Color")) {
if(color_in->link == NULL && gamma_in->link == NULL) {
- *optimized_value = svm_math_gamma_color(color_in->value,
- gamma_in->value.x);
+ optimized->set(svm_math_gamma_color(color_in->value(),
+ gamma_in->value_float()));
return true;
}
}
@@ -3556,10 +3567,10 @@ void GammaNode::compile(OSLCompiler& compiler)
BrightContrastNode::BrightContrastNode()
: ShaderNode("brightness")
{
- add_input("Color", SHADER_SOCKET_COLOR);
- add_input("Bright", SHADER_SOCKET_FLOAT);
- add_input("Contrast", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("Color", SocketType::COLOR);
+ add_input("Bright", SocketType::FLOAT);
+ add_input("Contrast", SocketType::FLOAT);
+ add_output("Color", SocketType::COLOR);
}
void BrightContrastNode::compile(SVMCompiler& compiler)
@@ -3586,10 +3597,10 @@ void BrightContrastNode::compile(OSLCompiler& compiler)
SeparateRGBNode::SeparateRGBNode()
: ShaderNode("separate_rgb")
{
- add_input("Image", SHADER_SOCKET_COLOR);
- add_output("R", SHADER_SOCKET_FLOAT);
- add_output("G", SHADER_SOCKET_FLOAT);
- add_output("B", SHADER_SOCKET_FLOAT);
+ add_input("Image", SocketType::COLOR);
+ add_output("R", SocketType::FLOAT);
+ add_output("G", SocketType::FLOAT);
+ add_output("B", SocketType::FLOAT);
}
void SeparateRGBNode::compile(SVMCompiler& compiler)
@@ -3621,10 +3632,10 @@ void SeparateRGBNode::compile(OSLCompiler& compiler)
SeparateXYZNode::SeparateXYZNode()
: ShaderNode("separate_xyz")
{
- add_input("Vector", SHADER_SOCKET_VECTOR);
- add_output("X", SHADER_SOCKET_FLOAT);
- add_output("Y", SHADER_SOCKET_FLOAT);
- add_output("Z", SHADER_SOCKET_FLOAT);
+ add_input("Vector", SocketType::VECTOR);
+ add_output("X", SocketType::FLOAT);
+ add_output("Y", SocketType::FLOAT);
+ add_output("Z", SocketType::FLOAT);
}
void SeparateXYZNode::compile(SVMCompiler& compiler)
@@ -3656,10 +3667,10 @@ void SeparateXYZNode::compile(OSLCompiler& compiler)
SeparateHSVNode::SeparateHSVNode()
: ShaderNode("separate_hsv")
{
- add_input("Color", SHADER_SOCKET_COLOR);
- add_output("H", SHADER_SOCKET_FLOAT);
- add_output("S", SHADER_SOCKET_FLOAT);
- add_output("V", SHADER_SOCKET_FLOAT);
+ add_input("Color", SocketType::COLOR);
+ add_output("H", SocketType::FLOAT);
+ add_output("S", SocketType::FLOAT);
+ add_output("V", SocketType::FLOAT);
}
void SeparateHSVNode::compile(SVMCompiler& compiler)
@@ -3686,12 +3697,12 @@ void SeparateHSVNode::compile(OSLCompiler& compiler)
HSVNode::HSVNode()
: ShaderNode("hsv")
{
- add_input("Hue", SHADER_SOCKET_FLOAT);
- add_input("Saturation", SHADER_SOCKET_FLOAT);
- add_input("Value", SHADER_SOCKET_FLOAT);
- add_input("Fac", SHADER_SOCKET_FLOAT);
- add_input("Color", SHADER_SOCKET_COLOR);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("Hue", SocketType::FLOAT);
+ add_input("Saturation", SocketType::FLOAT);
+ add_input("Value", SocketType::FLOAT);
+ add_input("Fac", SocketType::FLOAT);
+ add_input("Color", SocketType::COLOR);
+ add_output("Color", SocketType::COLOR);
}
void HSVNode::compile(SVMCompiler& compiler)
@@ -3726,9 +3737,9 @@ AttributeNode::AttributeNode()
{
attribute = "";
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Vector", SHADER_SOCKET_VECTOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ add_output("Color", SocketType::COLOR);
+ add_output("Vector", SocketType::VECTOR);
+ add_output("Fac", SocketType::FLOAT);
}
void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -3807,9 +3818,9 @@ void AttributeNode::compile(OSLCompiler& compiler)
CameraNode::CameraNode()
: ShaderNode("camera")
{
- add_output("View Vector", SHADER_SOCKET_VECTOR);
- add_output("View Z Depth", SHADER_SOCKET_FLOAT);
- add_output("View Distance", SHADER_SOCKET_FLOAT);
+ add_output("View Vector", SocketType::VECTOR);
+ add_output("View Z Depth", SocketType::FLOAT);
+ add_output("View Distance", SocketType::FLOAT);
}
void CameraNode::compile(SVMCompiler& compiler)
@@ -3834,9 +3845,9 @@ void CameraNode::compile(OSLCompiler& compiler)
FresnelNode::FresnelNode()
: ShaderNode("fresnel")
{
- add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_input("IOR", SHADER_SOCKET_FLOAT, 1.45f);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ add_input("Normal", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ add_input("IOR", SocketType::FLOAT, 1.45f);
+ add_output("Fac", SocketType::FLOAT);
}
void FresnelNode::compile(SVMCompiler& compiler)
@@ -3847,7 +3858,7 @@ void FresnelNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_FRESNEL,
compiler.stack_assign(IOR_in),
- __float_as_int(IOR_in->value.x),
+ __float_as_int(IOR_in->value_float()),
compiler.encode_uchar4(
compiler.stack_assign_if_linked(normal_in),
compiler.stack_assign(fac_out)));
@@ -3863,11 +3874,11 @@ void FresnelNode::compile(OSLCompiler& compiler)
LayerWeightNode::LayerWeightNode()
: ShaderNode("layer_weight")
{
- add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_input("Blend", SHADER_SOCKET_FLOAT, 0.5f);
+ add_input("Normal", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ add_input("Blend", SocketType::FLOAT, 0.5f);
- add_output("Fresnel", SHADER_SOCKET_FLOAT);
- add_output("Facing", SHADER_SOCKET_FLOAT);
+ add_output("Fresnel", SocketType::FLOAT);
+ add_output("Facing", SocketType::FLOAT);
}
void LayerWeightNode::compile(SVMCompiler& compiler)
@@ -3880,7 +3891,7 @@ void LayerWeightNode::compile(SVMCompiler& compiler)
if(!fresnel_out->links.empty()) {
compiler.add_node(NODE_LAYER_WEIGHT,
compiler.stack_assign_if_linked(blend_in),
- __float_as_int(blend_in->value.x),
+ __float_as_int(blend_in->value_float()),
compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL,
compiler.stack_assign_if_linked(normal_in),
compiler.stack_assign(fresnel_out)));
@@ -3889,7 +3900,7 @@ void LayerWeightNode::compile(SVMCompiler& compiler)
if(!facing_out->links.empty()) {
compiler.add_node(NODE_LAYER_WEIGHT,
compiler.stack_assign_if_linked(blend_in),
- __float_as_int(blend_in->value.x),
+ __float_as_int(blend_in->value_float()),
compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING,
compiler.stack_assign_if_linked(normal_in),
compiler.stack_assign(facing_out)));
@@ -3906,8 +3917,8 @@ void LayerWeightNode::compile(OSLCompiler& compiler)
WireframeNode::WireframeNode()
: ShaderNode("wireframe")
{
- add_input("Size", SHADER_SOCKET_FLOAT, 0.01f);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ add_input("Size", SocketType::FLOAT, 0.01f);
+ add_output("Fac", SocketType::FLOAT);
use_pixel_size = false;
}
@@ -3951,8 +3962,8 @@ void WireframeNode::compile(OSLCompiler& compiler)
WavelengthNode::WavelengthNode()
: ShaderNode("wavelength")
{
- add_input("Wavelength", SHADER_SOCKET_FLOAT, 500.0f);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("Wavelength", SocketType::FLOAT, 500.0f);
+ add_output("Color", SocketType::COLOR);
}
void WavelengthNode::compile(SVMCompiler& compiler)
@@ -3975,17 +3986,17 @@ void WavelengthNode::compile(OSLCompiler& compiler)
BlackbodyNode::BlackbodyNode()
: ShaderNode("blackbody")
{
- add_input("Temperature", SHADER_SOCKET_FLOAT, 1200.0f);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("Temperature", SocketType::FLOAT, 1200.0f);
+ add_output("Color", SocketType::COLOR);
}
-bool BlackbodyNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value)
+bool BlackbodyNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized)
{
ShaderInput *temperature_in = input("Temperature");
if(socket == output("Color")) {
if(temperature_in->link == NULL) {
- *optimized_value = svm_math_blackbody_color(temperature_in->value.x);
+ optimized->set(svm_math_blackbody_color(temperature_in->value_float()));
return true;
}
}
@@ -4015,10 +4026,10 @@ OutputNode::OutputNode()
{
special_type = SHADER_SPECIAL_TYPE_OUTPUT;
- add_input("Surface", SHADER_SOCKET_CLOSURE);
- add_input("Volume", SHADER_SOCKET_CLOSURE);
- add_input("Displacement", SHADER_SOCKET_FLOAT);
- add_input("Normal", SHADER_SOCKET_NORMAL);
+ add_input("Surface", SocketType::CLOSURE);
+ add_input("Volume", SocketType::CLOSURE);
+ add_input("Displacement", SocketType::FLOAT);
+ add_input("Normal", SocketType::NORMAL);
}
void OutputNode::compile(SVMCompiler& compiler)
@@ -4047,18 +4058,18 @@ void OutputNode::compile(OSLCompiler& compiler)
MathNode::MathNode()
: ShaderNode("math")
{
- type = ustring("Add");
+ type = NODE_MATH_ADD;
use_clamp = false;
- add_input("Value1", SHADER_SOCKET_FLOAT);
- add_input("Value2", SHADER_SOCKET_FLOAT);
- add_output("Value", SHADER_SOCKET_FLOAT);
+ add_input("Value1", SocketType::FLOAT);
+ add_input("Value2", SocketType::FLOAT);
+ add_output("Value", SocketType::FLOAT);
}
-static ShaderEnum math_type_init()
+static NodeEnum math_type_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Add", NODE_MATH_ADD);
enm.insert("Subtract", NODE_MATH_SUBTRACT);
@@ -4083,23 +4094,25 @@ static ShaderEnum math_type_init()
return enm;
}
-ShaderEnum MathNode::type_enum = math_type_init();
+NodeEnum MathNode::type_enum = math_type_init();
-bool MathNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value)
+bool MathNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized)
{
ShaderInput *value1_in = input("Value1");
ShaderInput *value2_in = input("Value2");
if(socket == output("Value")) {
if(value1_in->link == NULL && value2_in->link == NULL) {
- optimized_value->x = svm_math((NodeMath)type_enum[type],
- value1_in->value.x,
- value2_in->value.x);
+ float value = svm_math(type,
+ value1_in->value_float(),
+ value2_in->value_float());
if(use_clamp) {
- optimized_value->x = saturate(optimized_value->x);
+ value = saturate(value);
}
+ optimized->set(value);
+
return true;
}
}
@@ -4113,10 +4126,7 @@ void MathNode::compile(SVMCompiler& compiler)
ShaderInput *value2_in = input("Value2");
ShaderOutput *value_out = output("Value");
- compiler.add_node(NODE_MATH,
- type_enum[type],
- compiler.stack_assign(value1_in),
- compiler.stack_assign(value2_in));
+ compiler.add_node(NODE_MATH, type, compiler.stack_assign(value1_in), compiler.stack_assign(value2_in));
compiler.add_node(NODE_MATH, compiler.stack_assign(value_out));
if(use_clamp) {
@@ -4127,8 +4137,8 @@ void MathNode::compile(SVMCompiler& compiler)
void MathNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("type", type);
- compiler.parameter("Clamp", use_clamp);
+ compiler.parameter("type", type_enum[type]);
+ compiler.parameter("use_clamp", use_clamp);
compiler.add(this, "node_math");
}
@@ -4137,17 +4147,17 @@ void MathNode::compile(OSLCompiler& compiler)
VectorMathNode::VectorMathNode()
: ShaderNode("vector_math")
{
- type = ustring("Add");
+ type = NODE_VECTOR_MATH_ADD;
- add_input("Vector1", SHADER_SOCKET_VECTOR);
- add_input("Vector2", SHADER_SOCKET_VECTOR);
- add_output("Value", SHADER_SOCKET_FLOAT);
- add_output("Vector", SHADER_SOCKET_VECTOR);
+ add_input("Vector1", SocketType::VECTOR);
+ add_input("Vector2", SocketType::VECTOR);
+ add_output("Value", SocketType::FLOAT);
+ add_output("Vector", SocketType::VECTOR);
}
-static ShaderEnum vector_math_type_init()
+static NodeEnum vector_math_type_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Add", NODE_VECTOR_MATH_ADD);
enm.insert("Subtract", NODE_VECTOR_MATH_SUBTRACT);
@@ -4159,9 +4169,9 @@ static ShaderEnum vector_math_type_init()
return enm;
}
-ShaderEnum VectorMathNode::type_enum = vector_math_type_init();
+NodeEnum VectorMathNode::type_enum = vector_math_type_init();
-bool VectorMathNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value)
+bool VectorMathNode::constant_fold(ShaderGraph *, ShaderOutput *socket, ShaderInput *optimized)
{
ShaderInput *vector1_in = input("Vector1");
ShaderInput *vector2_in = input("Vector2");
@@ -4172,16 +4182,16 @@ bool VectorMathNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket
if(vector1_in->link == NULL && vector2_in->link == NULL) {
svm_vector_math(&value,
&vector,
- (NodeVectorMath)type_enum[type],
- vector1_in->value,
- vector2_in->value);
+ type,
+ vector1_in->value(),
+ vector2_in->value());
if(socket == output("Value")) {
- optimized_value->x = value;
+ optimized->set(value);
return true;
}
else if(socket == output("Vector")) {
- *optimized_value = vector;
+ optimized->set(vector);
return true;
}
}
@@ -4197,7 +4207,7 @@ void VectorMathNode::compile(SVMCompiler& compiler)
ShaderOutput *vector_out = output("Vector");
compiler.add_node(NODE_VECTOR_MATH,
- type_enum[type],
+ type,
compiler.stack_assign(vector1_in),
compiler.stack_assign(vector2_in));
compiler.add_node(NODE_VECTOR_MATH,
@@ -4207,7 +4217,7 @@ void VectorMathNode::compile(SVMCompiler& compiler)
void VectorMathNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("type", type);
+ compiler.parameter("type", type_enum[type]);
compiler.add(this, "node_vector_math");
}
@@ -4216,17 +4226,17 @@ void VectorMathNode::compile(OSLCompiler& compiler)
VectorTransformNode::VectorTransformNode()
: ShaderNode("vector_transform")
{
- type = ustring("Vector");
- convert_from = ustring("world");
- convert_to = ustring("object");
+ type = NODE_VECTOR_TRANSFORM_TYPE_VECTOR;
+ convert_from = NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD;
+ convert_to = NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT;
- add_input("Vector", SHADER_SOCKET_VECTOR);
- add_output("Vector", SHADER_SOCKET_VECTOR);
+ add_input("Vector", SocketType::VECTOR);
+ add_output("Vector", SocketType::VECTOR);
}
-static ShaderEnum vector_transform_type_init()
+static NodeEnum vector_transform_type_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
enm.insert("Point", NODE_VECTOR_TRANSFORM_TYPE_POINT);
@@ -4235,9 +4245,9 @@ static ShaderEnum vector_transform_type_init()
return enm;
}
-static ShaderEnum vector_transform_convert_space_init()
+static NodeEnum vector_transform_convert_space_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("world", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
enm.insert("object", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
@@ -4246,8 +4256,8 @@ static ShaderEnum vector_transform_convert_space_init()
return enm;
}
-ShaderEnum VectorTransformNode::type_enum = vector_transform_type_init();
-ShaderEnum VectorTransformNode::convert_space_enum = vector_transform_convert_space_init();
+NodeEnum VectorTransformNode::type_enum = vector_transform_type_init();
+NodeEnum VectorTransformNode::convert_space_enum = vector_transform_convert_space_init();
void VectorTransformNode::compile(SVMCompiler& compiler)
{
@@ -4255,18 +4265,16 @@ void VectorTransformNode::compile(SVMCompiler& compiler)
ShaderOutput *vector_out = output("Vector");
compiler.add_node(NODE_VECTOR_TRANSFORM,
- compiler.encode_uchar4(type_enum[type],
- convert_space_enum[convert_from],
- convert_space_enum[convert_to]),
+ compiler.encode_uchar4(type, convert_from, convert_to),
compiler.encode_uchar4(compiler.stack_assign(vector_in),
compiler.stack_assign(vector_out)));
}
void VectorTransformNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("type", type);
- compiler.parameter("convert_from", convert_from);
- compiler.parameter("convert_to", convert_to);
+ compiler.parameter("type", type_enum[type]);
+ compiler.parameter("convert_from", convert_space_enum[convert_from]);
+ compiler.parameter("convert_to", convert_space_enum[convert_to]);
compiler.add(this, "node_vector_transform");
}
@@ -4281,16 +4289,16 @@ BumpNode::BumpNode()
/* this input is used by the user, but after graph transform it is no longer
* used and moved to sampler center/x/y instead */
- add_input("Height", SHADER_SOCKET_FLOAT);
+ add_input("Height", SocketType::FLOAT);
- add_input("SampleCenter", SHADER_SOCKET_FLOAT);
- add_input("SampleX", SHADER_SOCKET_FLOAT);
- add_input("SampleY", SHADER_SOCKET_FLOAT);
- add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
- add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Distance", SHADER_SOCKET_FLOAT, 0.1f);
+ add_input("SampleCenter", SocketType::FLOAT);
+ add_input("SampleX", SocketType::FLOAT);
+ add_input("SampleY", SocketType::FLOAT);
+ add_input("Normal", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ add_input("Strength", SocketType::FLOAT, 1.0f);
+ add_input("Distance", SocketType::FLOAT, 0.1f);
- add_output("Normal", SHADER_SOCKET_NORMAL);
+ add_output("Normal", SocketType::NORMAL);
}
void BumpNode::compile(SVMCompiler& compiler)
@@ -4323,9 +4331,7 @@ void BumpNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_bump");
}
-bool BumpNode::constant_fold(ShaderGraph *graph,
- ShaderOutput * /*socket*/,
- float3 * /*optimized_value*/)
+bool BumpNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *)
{
ShaderInput *height_in = input("Height");
ShaderInput *normal_in = input("Normal");
@@ -4352,9 +4358,9 @@ bool BumpNode::constant_fold(ShaderGraph *graph,
RGBCurvesNode::RGBCurvesNode()
: ShaderNode("rgb_curves")
{
- add_input("Fac", SHADER_SOCKET_FLOAT);
- add_input("Color", SHADER_SOCKET_COLOR);
- add_output("Color", SHADER_SOCKET_COLOR);
+ add_input("Fac", SocketType::FLOAT);
+ add_input("Color", SocketType::COLOR);
+ add_output("Color", SocketType::COLOR);
min_x = 0.0f;
max_x = 1.0f;
@@ -4397,9 +4403,9 @@ void RGBCurvesNode::compile(OSLCompiler& compiler)
VectorCurvesNode::VectorCurvesNode()
: ShaderNode("vector_curves")
{
- add_input("Fac", SHADER_SOCKET_FLOAT);
- add_input("Vector", SHADER_SOCKET_VECTOR);
- add_output("Vector", SHADER_SOCKET_VECTOR);
+ add_input("Fac", SocketType::FLOAT);
+ add_input("Vector", SocketType::VECTOR);
+ add_output("Vector", SocketType::VECTOR);
min_x = 0.0f;
max_x = 1.0f;
@@ -4442,9 +4448,9 @@ void VectorCurvesNode::compile(OSLCompiler& compiler)
RGBRampNode::RGBRampNode()
: ShaderNode("rgb_ramp")
{
- add_input("Fac", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Alpha", SHADER_SOCKET_FLOAT);
+ add_input("Fac", SocketType::FLOAT);
+ add_output("Color", SocketType::COLOR);
+ add_output("Alpha", SocketType::FLOAT);
interpolate = true;
}
@@ -4477,7 +4483,7 @@ void RGBRampNode::compile(OSLCompiler& compiler)
compiler.parameter_color_array("ramp_color", ramp);
compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size());
- compiler.parameter("ramp_interpolate", interpolate);
+ compiler.parameter("interpolate", interpolate);
compiler.add(this, "node_rgb_ramp");
}
@@ -4487,8 +4493,8 @@ void RGBRampNode::compile(OSLCompiler& compiler)
SetNormalNode::SetNormalNode()
: ShaderNode("set_normal")
{
- add_input("Direction", SHADER_SOCKET_VECTOR);
- add_output("Normal", SHADER_SOCKET_NORMAL);
+ add_input("Direction", SocketType::VECTOR);
+ add_output("Normal", SocketType::NORMAL);
}
void SetNormalNode::compile(SVMCompiler& compiler)
@@ -4506,20 +4512,29 @@ void SetNormalNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_set_normal");
}
-/* OSLScriptNode */
+/* OSLNode */
-OSLScriptNode::OSLScriptNode()
-: ShaderNode("osl_script")
+OSLNode::OSLNode()
+: ShaderNode("osl_shader")
{
special_type = SHADER_SPECIAL_TYPE_SCRIPT;
}
-void OSLScriptNode::compile(SVMCompiler& /*compiler*/)
+OSLNode::~OSLNode()
+{
+}
+
+OSLNode* OSLNode::create(size_t)
+{
+ return new OSLNode();
+}
+
+void OSLNode::compile(SVMCompiler&)
{
/* doesn't work for SVM, obviously ... */
}
-void OSLScriptNode::compile(OSLCompiler& compiler)
+void OSLNode::compile(OSLCompiler& compiler)
{
if(!filepath.empty())
compiler.add(this, filepath.c_str(), true);
@@ -4529,9 +4544,9 @@ void OSLScriptNode::compile(OSLCompiler& compiler)
/* Normal Map */
-static ShaderEnum normal_map_space_init()
+static NodeEnum normal_map_space_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Tangent", NODE_NORMAL_MAP_TANGENT);
enm.insert("Object", NODE_NORMAL_MAP_OBJECT);
@@ -4542,24 +4557,24 @@ static ShaderEnum normal_map_space_init()
return enm;
}
-ShaderEnum NormalMapNode::space_enum = normal_map_space_init();
+NodeEnum NormalMapNode::space_enum = normal_map_space_init();
NormalMapNode::NormalMapNode()
: ShaderNode("normal_map")
{
- space = ustring("Tangent");
+ space = NODE_NORMAL_MAP_TANGENT;
attribute = ustring("");
- add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Color", SHADER_SOCKET_COLOR);
+ add_input("NormalIn", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ add_input("Strength", SocketType::FLOAT, 1.0f);
+ add_input("Color", SocketType::COLOR);
- add_output("Normal", SHADER_SOCKET_NORMAL);
+ add_output("Normal", SocketType::NORMAL);
}
void NormalMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface && space == ustring("Tangent")) {
+ if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
if(attribute == ustring("")) {
attributes->add(ATTR_STD_UV_TANGENT);
attributes->add(ATTR_STD_UV_TANGENT_SIGN);
@@ -4582,7 +4597,7 @@ void NormalMapNode::compile(SVMCompiler& compiler)
ShaderOutput *normal_out = output("Normal");
int attr = 0, attr_sign = 0;
- if(space == ustring("Tangent")) {
+ if(space == NODE_NORMAL_MAP_TANGENT) {
if(attribute == ustring("")) {
attr = compiler.attribute(ATTR_STD_UV_TANGENT);
attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
@@ -4598,13 +4613,13 @@ void NormalMapNode::compile(SVMCompiler& compiler)
compiler.stack_assign(color_in),
compiler.stack_assign(strength_in),
compiler.stack_assign(normal_out),
- space_enum[space]),
+ space),
attr, attr_sign);
}
void NormalMapNode::compile(OSLCompiler& compiler)
{
- if(space == ustring("Tangent")) {
+ if(space == NODE_NORMAL_MAP_TANGENT) {
if(attribute == ustring("")) {
compiler.parameter("attr_name", ustring("geom:tangent"));
compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
@@ -4615,16 +4630,16 @@ void NormalMapNode::compile(OSLCompiler& compiler)
}
}
- compiler.parameter("space", space);
+ compiler.parameter("space", space_enum[space]);
compiler.add(this, "node_normal_map");
}
/* Tangent */
-static ShaderEnum tangent_direction_type_init()
+static NodeEnum tangent_direction_type_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("Radial", NODE_TANGENT_RADIAL);
enm.insert("UV Map", NODE_TANGENT_UVMAP);
@@ -4632,9 +4647,9 @@ static ShaderEnum tangent_direction_type_init()
return enm;
}
-static ShaderEnum tangent_axis_init()
+static NodeEnum tangent_axis_init()
{
- ShaderEnum enm;
+ NodeEnum enm;
enm.insert("X", NODE_TANGENT_AXIS_X);
enm.insert("Y", NODE_TANGENT_AXIS_Y);
@@ -4643,24 +4658,24 @@ static ShaderEnum tangent_axis_init()
return enm;
}
-ShaderEnum TangentNode::direction_type_enum = tangent_direction_type_init();
-ShaderEnum TangentNode::axis_enum = tangent_axis_init();
+NodeEnum TangentNode::direction_type_enum = tangent_direction_type_init();
+NodeEnum TangentNode::axis_enum = tangent_axis_init();
TangentNode::TangentNode()
: ShaderNode("tangent")
{
- direction_type = ustring("Radial");
- axis = ustring("X");
+ direction_type = NODE_TANGENT_RADIAL;
+ axis = NODE_TANGENT_AXIS_X;
attribute = ustring("");
- add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_output("Tangent", SHADER_SOCKET_NORMAL);
+ add_input("NormalIn", SocketType::NORMAL, make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+ add_output("Tangent", SocketType::NORMAL);
}
void TangentNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if(shader->has_surface) {
- if(direction_type == ustring("UV Map")) {
+ if(direction_type == NODE_TANGENT_UVMAP) {
if(attribute == ustring(""))
attributes->add(ATTR_STD_UV_TANGENT);
else
@@ -4678,7 +4693,7 @@ void TangentNode::compile(SVMCompiler& compiler)
ShaderOutput *tangent_out = output("Tangent");
int attr;
- if(direction_type == ustring("UV Map")) {
+ if(direction_type == NODE_TANGENT_UVMAP) {
if(attribute == ustring(""))
attr = compiler.attribute(ATTR_STD_UV_TANGENT);
else
@@ -4690,21 +4705,21 @@ void TangentNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_TANGENT,
compiler.encode_uchar4(
compiler.stack_assign(tangent_out),
- direction_type_enum[direction_type],
- axis_enum[axis]), attr);
+ direction_type,
+ axis), attr);
}
void TangentNode::compile(OSLCompiler& compiler)
{
- if(direction_type == ustring("UV Map")) {
+ if(direction_type == NODE_TANGENT_UVMAP) {
if(attribute == ustring(""))
compiler.parameter("attr_name", ustring("geom:tangent"));
else
compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
}
- compiler.parameter("direction_type", direction_type);
- compiler.parameter("axis", axis);
+ compiler.parameter("direction_type", direction_type_enum[direction_type]);
+ compiler.parameter("axis", axis_enum[axis]);
compiler.add(this, "node_tangent");
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 5df34a84559..8b17e455f7a 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -49,15 +49,15 @@ public:
enum Type { POINT = 0, TEXTURE = 1, VECTOR = 2, NORMAL = 3 };
Type type;
- static ShaderEnum type_enum;
+ static NodeEnum type_enum;
enum Mapping { NONE = 0, X = 1, Y = 2, Z = 3 };
Mapping x_mapping, y_mapping, z_mapping;
- static ShaderEnum mapping_enum;
+ static NodeEnum mapping_enum;
enum Projection { FLAT, CUBE, TUBE, SPHERE };
Projection projection;
- static ShaderEnum projection_enum;
+ static NodeEnum projection_enum;
bool equals(const TextureMapping& other) {
return translation == other.translation &&
@@ -109,15 +109,15 @@ public:
bool use_alpha;
string filename;
void *builtin_data;
- ustring color_space;
- ustring projection;
+ NodeImageColorSpace color_space;
+ NodeImageProjection projection;
InterpolationType interpolation;
ExtensionType extension;
float projection_blend;
bool animated;
- static ShaderEnum color_space_enum;
- static ShaderEnum projection_enum;
+ static NodeEnum color_space_enum;
+ static NodeEnum projection_enum;
virtual bool equals(const ShaderNode *other) {
const ImageTextureNode *image_node = (const ImageTextureNode*)other;
@@ -148,13 +148,13 @@ public:
bool use_alpha;
string filename;
void *builtin_data;
- ustring color_space;
- ustring projection;
+ NodeImageColorSpace color_space;
+ NodeEnvironmentProjection projection;
InterpolationType interpolation;
bool animated;
- static ShaderEnum color_space_enum;
- static ShaderEnum projection_enum;
+ static NodeEnum color_space_enum;
+ static NodeEnum projection_enum;
virtual bool equals(const ShaderNode *other) {
const EnvironmentTextureNode *env_node = (const EnvironmentTextureNode*)other;
@@ -175,12 +175,12 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ NodeSkyType type;
float3 sun_direction;
float turbidity;
float ground_albedo;
- ustring type;
- static ShaderEnum type_enum;
+ static NodeEnum type_enum;
virtual bool equals(const ShaderNode *other) {
const SkyTextureNode *sky_node = (const SkyTextureNode*)other;
@@ -206,8 +206,8 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
- ustring type;
- static ShaderEnum type_enum;
+ NodeGradientType type;
+ static NodeEnum type_enum;
virtual bool equals(const ShaderNode *other) {
const GradientTextureNode *gradient_node = (const GradientTextureNode*)other;
@@ -227,9 +227,8 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
- ustring coloring;
-
- static ShaderEnum coloring_enum;
+ NodeVoronoiColoring coloring;
+ static NodeEnum coloring_enum;
virtual bool equals(const ShaderNode *other) {
const VoronoiTextureNode *voronoi_node = (const VoronoiTextureNode*)other;
@@ -244,9 +243,8 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
- ustring type;
-
- static ShaderEnum type_enum;
+ NodeMusgraveType type;
+ static NodeEnum type_enum;
virtual bool equals(const ShaderNode *other) {
const MusgraveTextureNode *musgrave_node = (const MusgraveTextureNode*)other;
@@ -261,10 +259,10 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
- ustring type;
- ustring profile;
- static ShaderEnum type_enum;
- static ShaderEnum profile_enum;
+ NodeWaveType type;
+ NodeWaveProfile profile;
+ static NodeEnum type_enum;
+ static NodeEnum profile_enum;
virtual bool equals(const ShaderNode *other) {
const WaveTextureNode *wave_node = (const WaveTextureNode*)other;
@@ -329,13 +327,13 @@ public:
ImageManager *image_manager;
int slot;
string filename;
- ustring space;
+ NodeTexVoxelSpace space;
void *builtin_data;
InterpolationType interpolation;
Transform tfm;
- static ShaderEnum space_enum;
+ static NodeEnum space_enum;
virtual bool equals(const ShaderNode *other) {
const PointDensityTextureNode *point_dendity_node = (const PointDensityTextureNode*)other;
@@ -362,14 +360,21 @@ public:
}
};
+class RGBToBWNode : public ShaderNode {
+public:
+ SHADER_NODE_CLASS(RGBToBWNode)
+
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
+};
+
class ConvertNode : public ShaderNode {
public:
- ConvertNode(ShaderSocketType from, ShaderSocketType to, bool autoconvert = false);
+ ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert = false);
SHADER_NODE_BASE_CLASS(ConvertNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
- ShaderSocketType from, to;
+ SocketType::Type from, to;
virtual bool equals(const ShaderNode *other)
{
@@ -403,8 +408,8 @@ class AnisotropicBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(AnisotropicBsdfNode)
- ustring distribution;
- static ShaderEnum distribution_enum;
+ ClosureType distribution;
+ static NodeEnum distribution_enum;
void attributes(Shader *shader, AttributeRequestSet *attributes);
};
@@ -438,8 +443,8 @@ public:
void simplify_settings(Scene *scene);
bool has_integrator_dependency();
- ustring distribution, distribution_orig;
- static ShaderEnum distribution_enum;
+ ClosureType distribution, distribution_orig;
+ static NodeEnum distribution_enum;
};
class GlassBsdfNode : public BsdfNode {
@@ -449,8 +454,8 @@ public:
void simplify_settings(Scene *scene);
bool has_integrator_dependency();
- ustring distribution, distribution_orig;
- static ShaderEnum distribution_enum;
+ ClosureType distribution, distribution_orig;
+ static NodeEnum distribution_enum;
};
class RefractionBsdfNode : public BsdfNode {
@@ -460,16 +465,16 @@ public:
void simplify_settings(Scene *scene);
bool has_integrator_dependency();
- ustring distribution, distribution_orig;
- static ShaderEnum distribution_enum;
+ ClosureType distribution, distribution_orig;
+ static NodeEnum distribution_enum;
};
class ToonBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(ToonBsdfNode)
- ustring component;
- static ShaderEnum component_enum;
+ ClosureType component;
+ static NodeEnum component_enum;
};
class SubsurfaceScatteringNode : public BsdfNode {
@@ -478,13 +483,14 @@ public:
bool has_surface_bssrdf() { return true; }
bool has_bssrdf_bump();
- static ShaderEnum falloff_enum;
+ ClosureType falloff;
+ static NodeEnum falloff_enum;
};
class EmissionNode : public ShaderNode {
public:
SHADER_NODE_CLASS(EmissionNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
virtual ClosureType get_closure_type() { return CLOSURE_EMISSION_ID; }
bool has_surface_emission() { return true; }
@@ -493,7 +499,7 @@ public:
class BackgroundNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BackgroundNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
virtual ClosureType get_closure_type() { return CLOSURE_BACKGROUND_ID; }
};
@@ -547,8 +553,8 @@ class HairBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(HairBsdfNode)
- ustring component;
- static ShaderEnum component_enum;
+ ClosureType component;
+ static NodeEnum component_enum;
};
@@ -639,7 +645,7 @@ class ValueNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ValueNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
float value;
@@ -654,7 +660,7 @@ class ColorNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ColorNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
float3 value;
@@ -673,7 +679,7 @@ public:
class MixClosureNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixClosureNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
};
class MixClosureWeightNode : public ShaderNode {
@@ -691,14 +697,14 @@ public:
class MixNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
bool use_clamp;
- ustring type;
- static ShaderEnum type_enum;
+ NodeMix type;
+ static NodeEnum type_enum;
virtual bool equals(const ShaderNode *other)
{
@@ -734,7 +740,7 @@ class GammaNode : public ShaderNode {
public:
SHADER_NODE_CLASS(GammaNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
};
@@ -825,7 +831,7 @@ public:
class BlackbodyNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BlackbodyNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
};
@@ -834,12 +840,12 @@ class MathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
bool use_clamp;
- ustring type;
- static ShaderEnum type_enum;
+ NodeMath type;
+ static NodeEnum type_enum;
virtual bool equals(const ShaderNode *other)
{
@@ -869,14 +875,14 @@ class VectorMathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorMathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
- ustring type;
- static ShaderEnum type_enum;
+ NodeVectorMath type;
+ static NodeEnum type_enum;
virtual bool equals(const ShaderNode *other)
{
- const MathNode *math_node = (const MathNode*)other;
+ const VectorMathNode *math_node = (const VectorMathNode*)other;
return ShaderNode::equals(other) &&
type == math_node->type;
}
@@ -888,12 +894,12 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- ustring type;
- ustring convert_from;
- ustring convert_to;
+ NodeVectorTransformType type;
+ NodeVectorTransformConvertSpace convert_from;
+ NodeVectorTransformConvertSpace convert_to;
- static ShaderEnum type_enum;
- static ShaderEnum convert_space_enum;
+ static NodeEnum type_enum;
+ static NodeEnum convert_space_enum;
virtual bool equals(const ShaderNode *other) {
const VectorTransformNode *vector_transform_node = (const VectorTransformNode*)other;
@@ -907,7 +913,7 @@ public:
class BumpNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BumpNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, ShaderInput *optimized);
bool has_spatial_varying() { return true; }
virtual int get_feature() {
return NODE_FEATURE_BUMP;
@@ -959,17 +965,22 @@ public:
SHADER_NODE_CLASS(SetNormalNode)
};
-class OSLScriptNode : public ShaderNode {
+class OSLNode : public ShaderNode {
public:
- SHADER_NODE_CLASS(OSLScriptNode)
+ static OSLNode *create(size_t num_inputs);
+ ~OSLNode();
+
+ SHADER_NODE_BASE_CLASS(OSLNode)
/* ideally we could beter detect this, but we can't query this now */
bool has_spatial_varying() { return true; }
+ virtual bool equals(const ShaderNode * /*other*/) { return false; }
string filepath;
string bytecode_hash;
- virtual bool equals(const ShaderNode * /*other*/) { return false; }
+private:
+ OSLNode();
};
class NormalMapNode : public ShaderNode {
@@ -979,8 +990,8 @@ public:
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- ustring space;
- static ShaderEnum space_enum;
+ NodeNormalMapSpace space;
+ static NodeEnum space_enum;
ustring attribute;
@@ -1000,11 +1011,10 @@ public:
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- ustring direction_type;
- static ShaderEnum direction_type_enum;
-
- ustring axis;
- static ShaderEnum axis_enum;
+ NodeTangentDirectionType direction_type;
+ NodeTangentAxis axis;
+ static NodeEnum direction_type_enum;
+ static NodeEnum axis_enum;
ustring attribute;
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index e2fe0bd72a1..9ee1a9ef7a6 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -33,14 +33,25 @@ CCL_NAMESPACE_BEGIN
/* Object */
+NODE_DEFINE(Object)
+{
+ NodeType* type = NodeType::add("object", create);
+
+ SOCKET_NODE(mesh, "Mesh", &Mesh::node_type);
+ SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
+ SOCKET_INT(visibility, "Visibility", ~0);
+ SOCKET_INT(random_id, "Random ID", 0);
+ SOCKET_INT(pass_id, "Pass ID", 0);
+ SOCKET_BOOLEAN(use_holdout, "Use Holdout", false);
+ SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
+
+ return type;
+}
+
Object::Object()
+: Node(node_type)
{
- name = "";
- mesh = NULL;
- tfm = transform_identity();
- visibility = ~0;
- random_id = 0;
- pass_id = 0;
particle_system = NULL;
particle_index = 0;
bounds = BoundBox::empty;
@@ -48,9 +59,6 @@ Object::Object()
motion.mid = transform_identity();
motion.post = transform_identity();
use_motion = false;
- use_holdout = false;
- dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
- dupli_uv = make_float2(0.0f, 0.0f);
}
Object::~Object()
@@ -137,12 +145,12 @@ void Object::apply_transform(bool apply_to_motion)
/* apply transform to curve keys */
for(size_t i = 0; i < mesh->curve_keys.size(); i++) {
- float3 co = transform_point(&tfm, float4_to_float3(mesh->curve_keys[i]));
- float radius = mesh->curve_keys[i].w * scalar;
+ float3 co = transform_point(&tfm, mesh->curve_keys[i]);
+ float radius = mesh->curve_radius[i] * scalar;
/* scale for curve radius is only correct for uniform scale */
- mesh->curve_keys[i] = float3_to_float4(co);
- mesh->curve_keys[i].w = radius;
+ mesh->curve_keys[i] = co;
+ mesh->curve_radius[i] = radius;
}
if(apply_to_motion) {
@@ -269,7 +277,9 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
state->surface_area_lock.unlock();
if(it == state->surface_area_map.end()) {
- foreach(Mesh::Triangle& t, mesh->triangles) {
+ size_t num_triangles = mesh->num_triangles();
+ for(size_t j = 0; j < num_triangles; j++) {
+ Mesh::Triangle t = mesh->get_triangle(j);
float3 p1 = mesh->verts[t.v[0]];
float3 p2 = mesh->verts[t.v[1]];
float3 p3 = mesh->verts[t.v[2]];
@@ -288,7 +298,9 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
surface_area *= uniform_scale;
}
else {
- foreach(Mesh::Triangle& t, mesh->triangles) {
+ size_t num_triangles = mesh->num_triangles();
+ for(size_t j = 0; j < num_triangles; j++) {
+ Mesh::Triangle t = mesh->get_triangle(j);
float3 p1 = transform_point(&tfm, mesh->verts[t.v[0]]);
float3 p2 = transform_point(&tfm, mesh->verts[t.v[1]]);
float3 p3 = transform_point(&tfm, mesh->verts[t.v[2]]);
@@ -360,7 +372,7 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
state->object_flag[object_index] = flag;
/* Have curves. */
- if(mesh->curves.size()) {
+ if(mesh->num_curves()) {
state->have_curves = true;
}
}
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index c2a79ca8dc4..57614c95580 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -17,6 +17,7 @@
#ifndef __OBJECT_H__
#define __OBJECT_H__
+#include "node.h"
#include "scene.h"
#include "util_boundbox.h"
@@ -37,12 +38,13 @@ struct Transform;
/* Object */
-class Object {
+class Object : public Node {
public:
+ NODE_DECLARE;
+
Mesh *mesh;
Transform tfm;
BoundBox bounds;
- ustring name;
uint random_id;
int pass_id;
vector<ParamValue> attributes;
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 3d14965b4ca..1cfe3fb38e2 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -394,16 +394,143 @@ const char *OSLShaderManager::shader_load_bytecode(const string& hash, const str
{
ss->LoadMemoryCompiledShader(hash.c_str(), bytecode.c_str());
- /* this is a bit weak, but works */
OSLShaderInfo info;
+
+ if(!info.query.open_bytecode(bytecode)) {
+ fprintf(stderr, "OSL query error: %s\n", info.query.geterror().c_str());
+ }
+
+ /* this is a bit weak, but works */
info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos);
info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos);
info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos);
+
loaded_shaders[hash] = info;
return loaded_shaders.find(hash)->first.c_str();
}
+OSLNode *OSLShaderManager::osl_node(const std::string& filepath,
+ const std::string& bytecode_hash,
+ const std::string& bytecode)
+{
+ /* create query */
+ const char *hash;
+
+ if(!filepath.empty()) {
+ hash = shader_load_filepath(filepath);
+ }
+ else {
+ hash = shader_test_loaded(bytecode_hash);
+ if(!hash)
+ hash = shader_load_bytecode(bytecode_hash, bytecode);
+ }
+
+ if(!hash) {
+ return NULL;
+ }
+
+ OSLShaderInfo *info = shader_loaded_info(hash);
+
+ /* count number of inputs */
+ size_t num_inputs = 0;
+
+ for(int i = 0; i < info->query.nparams(); i++) {
+ const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
+
+ /* skip unsupported types */
+ if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
+ continue;
+
+ if(!param->isoutput)
+ num_inputs++;
+ }
+
+ /* create node */
+ OSLNode *node = OSLNode::create(num_inputs);
+
+ /* add new sockets from parameters */
+ set<void*> used_sockets;
+
+ for(int i = 0; i < info->query.nparams(); i++) {
+ const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
+
+ /* skip unsupported types */
+ if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
+ continue;
+
+ SocketType::Type socket_type;
+
+ if(param->isclosure) {
+ socket_type = SocketType::CLOSURE;
+ }
+ else if(param->type.vecsemantics != TypeDesc::NOSEMANTICS) {
+ if(param->type.vecsemantics == TypeDesc::COLOR)
+ socket_type = SocketType::COLOR;
+ else if(param->type.vecsemantics == TypeDesc::POINT)
+ socket_type = SocketType::POINT;
+ else if(param->type.vecsemantics == TypeDesc::VECTOR)
+ socket_type = SocketType::VECTOR;
+ else if(param->type.vecsemantics == TypeDesc::NORMAL)
+ socket_type = SocketType::NORMAL;
+ else
+ continue;
+
+ if(!param->isoutput && param->validdefault) {
+ node->add_input(param->name.c_str(), socket_type, make_float3(param->fdefault[0], param->fdefault[1], param->fdefault[2]));
+ continue;
+ }
+ }
+ else if(param->type.aggregate == TypeDesc::SCALAR) {
+ if(param->type.basetype == TypeDesc::INT) {
+ socket_type = SocketType::INT;
+
+ if(!param->isoutput && param->validdefault) {
+ node->add_input(param->name.c_str(), socket_type, (float)param->idefault[0]);
+ continue;
+ }
+ }
+ else if(param->type.basetype == TypeDesc::FLOAT) {
+ socket_type = SocketType::FLOAT;
+
+ if(!param->isoutput && param->validdefault) {
+ node->add_input(param->name.c_str(), socket_type, param->fdefault[0]);
+ continue;
+ }
+ }
+ else if(param->type.basetype == TypeDesc::STRING) {
+ socket_type = SocketType::STRING;
+
+ if(!param->isoutput && param->validdefault) {
+ node->add_input(param->name.c_str(), socket_type);
+ continue;
+ }
+ }
+ else
+ continue;
+ }
+ else
+ continue;
+
+ if(param->isoutput) {
+ node->add_output(param->name.c_str(), socket_type);
+ }
+ else {
+ node->add_input(param->name.c_str(), socket_type);
+ }
+ }
+
+ /* set bytcode hash or filepath */
+ if(!bytecode_hash.empty()) {
+ node->bytecode_hash = bytecode_hash;
+ }
+ else {
+ node->filepath = filepath;
+ }
+
+ return node;
+}
+
/* Graph Compiler */
OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_, ImageManager *image_manager_)
@@ -427,7 +554,7 @@ string OSLCompiler::id(ShaderNode *node)
string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
{
- string sname(input->name);
+ string sname(input->name().string());
size_t i;
/* strip whitespace */
@@ -436,7 +563,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
/* if output exists with the same name, add "In" suffix */
foreach(ShaderOutput *output, node->outputs) {
- if(strcmp(input->name, output->name)==0) {
+ if(input->name() == output->name()) {
sname += "In";
break;
}
@@ -447,7 +574,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
{
- string sname(output->name);
+ string sname(output->name().string());
size_t i;
/* strip whitespace */
@@ -456,7 +583,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
/* if input exists with the same name, add "Out" suffix */
foreach(ShaderInput *input, node->inputs) {
- if(strcmp(input->name, output->name)==0) {
+ if(input->name() == output->name()) {
sname += "Out";
break;
}
@@ -470,21 +597,21 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
/* exception for output node, only one input is actually used
* depending on the current shader type */
- if(!(input->usage & ShaderInput::USE_OSL))
+ if(input->flags() & SocketType::SVM_INTERNAL)
return true;
if(node->special_type == SHADER_SPECIAL_TYPE_OUTPUT) {
- if(strcmp(input->name, "Surface") == 0 && current_type != SHADER_TYPE_SURFACE)
+ if(input->name() == "Surface" && current_type != SHADER_TYPE_SURFACE)
return true;
- if(strcmp(input->name, "Volume") == 0 && current_type != SHADER_TYPE_VOLUME)
+ if(input->name() == "Volume" && current_type != SHADER_TYPE_VOLUME)
return true;
- if(strcmp(input->name, "Displacement") == 0 && current_type != SHADER_TYPE_DISPLACEMENT)
+ if(input->name() == "Displacement" && current_type != SHADER_TYPE_DISPLACEMENT)
return true;
- if(strcmp(input->name, "Normal") == 0)
+ if(input->name() == "Normal")
return true;
}
else if(node->special_type == SHADER_SPECIAL_TYPE_BUMP) {
- if(strcmp(input->name, "Height") == 0)
+ if(input->name() == "Height")
return true;
}
else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->special_type == SHADER_SPECIAL_TYPE_BUMP)
@@ -512,34 +639,35 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
if(node_skip_input(node, input))
continue;
/* already has default value assigned */
- else if(input->default_value != ShaderInput::NONE)
+ else if(input->flags() & SocketType::DEFAULT_LINK_MASK)
continue;
string param_name = compatible_name(node, input);
- switch(input->type) {
- case SHADER_SOCKET_COLOR:
- parameter_color(param_name.c_str(), input->value);
+ switch(input->type()) {
+ case SocketType::COLOR:
+ parameter_color(param_name.c_str(), input->value());
break;
- case SHADER_SOCKET_POINT:
- parameter_point(param_name.c_str(), input->value);
+ case SocketType::POINT:
+ parameter_point(param_name.c_str(), input->value());
break;
- case SHADER_SOCKET_VECTOR:
- parameter_vector(param_name.c_str(), input->value);
+ case SocketType::VECTOR:
+ parameter_vector(param_name.c_str(), input->value());
break;
- case SHADER_SOCKET_NORMAL:
- parameter_normal(param_name.c_str(), input->value);
+ case SocketType::NORMAL:
+ parameter_normal(param_name.c_str(), input->value());
break;
- case SHADER_SOCKET_FLOAT:
- parameter(param_name.c_str(), input->value.x);
+ case SocketType::FLOAT:
+ parameter(param_name.c_str(), input->value_float());
break;
- case SHADER_SOCKET_INT:
- parameter(param_name.c_str(), (int)input->value.x);
+ case SocketType::INT:
+ parameter(param_name.c_str(), (int)input->value_float());
break;
- case SHADER_SOCKET_STRING:
- parameter(param_name.c_str(), input->value_string);
+ case SocketType::STRING:
+ parameter(param_name.c_str(), input->value_string());
break;
- case SHADER_SOCKET_CLOSURE:
- case SHADER_SOCKET_UNDEFINED:
+ case SocketType::CLOSURE:
+ case SocketType::UNDEFINED:
+ default:
break;
}
}
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 110897ff300..13b9d6307f9 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -22,6 +22,7 @@
#include "util_thread.h"
#include "graph.h"
+#include "nodes.h"
#include "shader.h"
#ifdef WITH_OSL
@@ -54,6 +55,7 @@ struct OSLShaderInfo {
has_surface_bssrdf(false)
{}
+ OSL::OSLQuery query;
bool has_surface_emission;
bool has_surface_transparent;
bool has_surface_bssrdf;
@@ -83,6 +85,11 @@ public:
const char *shader_load_filepath(string filepath);
OSLShaderInfo *shader_loaded_info(const string& hash);
+ /* create OSL node using OSLQuery */
+ OSLNode *osl_node(const std::string& filepath,
+ const std::string& bytecode_hash = "",
+ const std::string& bytecode = "");
+
protected:
void texture_system_init();
void texture_system_free();
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index 50726bb4574..1a35d60fb4b 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -58,8 +58,8 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene
* adds one dummy particle at the beginning to avoid invalid lookups,
* in case a shader uses particle info without actual particle data. */
int num_particles = 1;
- foreach(ParticleSystem *psys, scene->particle_systems)
- num_particles += psys->particles.size();
+ for(size_t j = 0; j < scene->particle_systems.size(); j++)
+ num_particles += scene->particle_systems[j]->particles.size();
float4 *particles = dscene->particles.resize(PARTICLE_SIZE*num_particles);
@@ -71,9 +71,12 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene
particles[4] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
int i = 1;
- foreach(ParticleSystem *psys, scene->particle_systems) {
- foreach(Particle &pa, psys->particles) {
+ for(size_t j = 0; j < scene->particle_systems.size(); j++) {
+ ParticleSystem *psys = scene->particle_systems[j];
+
+ for(size_t k = 0; k < psys->particles.size(); k++) {
/* pack in texture */
+ Particle& pa = psys->particles[k];
int offset = i*PARTICLE_SIZE;
particles[offset] = make_float4(pa.index, pa.age, pa.lifetime, pa.size);
diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h
index bf2b6b77015..2509e27b44b 100644
--- a/intern/cycles/render/particles.h
+++ b/intern/cycles/render/particles.h
@@ -47,7 +47,7 @@ public:
void tag_update(Scene *scene);
- vector<Particle> particles;
+ array<Particle> particles;
};
/* ParticleSystem Manager */
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index b0052c30af4..e8367e1eb36 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -242,9 +242,14 @@ void Scene::device_update(Device *device_, Progress& progress)
}
if(print_stats) {
+ size_t mem_used = util_guarded_get_mem_used();
+ size_t mem_peak = util_guarded_get_mem_peak();
+
VLOG(1) << "System memory statistics after full device sync:\n"
- << " Usage: " << util_guarded_get_mem_used() << "\n"
- << " Peak: " << util_guarded_get_mem_peak();
+ << " Usage: " << string_human_readable_number(mem_used)
+ << " (" << string_human_readable_size(mem_used) << ")\n"
+ << " Peak: " << string_human_readable_number(mem_peak)
+ << " (" << string_human_readable_size(mem_peak) << ")";
}
}
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 33c03d40f27..b34d6127118 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -109,10 +109,10 @@ public:
device_vector<uint> sobol_directions;
/* cpu images */
- device_vector<uchar4> tex_byte4_image[TEX_NUM_BYTE4_IMAGES_CPU];
- device_vector<float4> tex_float4_image[TEX_NUM_FLOAT4_IMAGES_CPU];
- device_vector<float> tex_float_image[TEX_NUM_FLOAT_IMAGES_CPU];
- device_vector<uchar> tex_byte_image[TEX_NUM_BYTE_IMAGES_CPU];
+ device_vector<uchar4> tex_byte4_image[TEX_NUM_BYTE4_CPU];
+ device_vector<float4> tex_float4_image[TEX_NUM_FLOAT4_CPU];
+ device_vector<float> tex_float_image[TEX_NUM_FLOAT_CPU];
+ device_vector<uchar> tex_byte_image[TEX_NUM_BYTE_CPU];
/* opencl images */
device_vector<uchar4> tex_image_byte4_packed;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 76979e9ba3e..1cd76ff2b39 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -630,7 +630,7 @@ DeviceRequestedFeatures Session::get_requested_device_features()
requested_features.use_camera_motion = scene->camera->use_motion;
foreach(Object *object, scene->objects) {
Mesh *mesh = object->mesh;
- if(mesh->curves.size() > 0) {
+ if(mesh->num_curves()) {
requested_features.use_hair = true;
}
requested_features.use_object_motion |= object->use_motion | mesh->use_motion_blur;
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 635024d7bdf..708eeef3b50 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -456,7 +456,7 @@ void ShaderManager::add_default(Scene *scene)
ShaderGraph *graph = new ShaderGraph();
closure = graph->add(new DiffuseBsdfNode());
- closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
+ closure->input("Color")->set(make_float3(0.8f, 0.8f, 0.8f));
out = graph->output();
graph->connect(closure->output("BSDF"), out->input("Surface"));
@@ -473,8 +473,8 @@ void ShaderManager::add_default(Scene *scene)
ShaderGraph *graph = new ShaderGraph();
closure = graph->add(new EmissionNode());
- closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
- closure->input("Strength")->value.x = 0.0f;
+ closure->input("Color")->set(make_float3(0.8f, 0.8f, 0.8f));
+ closure->input("Strength")->set(0.0f);
out = graph->output();
graph->connect(closure->output("Emission"), out->input("Surface"));
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 4c97a5ad792..d54afd1ba6f 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -120,22 +120,22 @@ SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_man
compile_failed = false;
}
-int SVMCompiler::stack_size(ShaderSocketType type)
+int SVMCompiler::stack_size(SocketType::Type type)
{
int size = 0;
switch(type) {
- case SHADER_SOCKET_FLOAT:
- case SHADER_SOCKET_INT:
+ case SocketType::FLOAT:
+ case SocketType::INT:
size = 1;
break;
- case SHADER_SOCKET_COLOR:
- case SHADER_SOCKET_VECTOR:
- case SHADER_SOCKET_NORMAL:
- case SHADER_SOCKET_POINT:
+ case SocketType::COLOR:
+ case SocketType::VECTOR:
+ case SocketType::NORMAL:
+ case SocketType::POINT:
size = 3;
break;
- case SHADER_SOCKET_CLOSURE:
+ case SocketType::CLOSURE:
size = 0;
break;
default:
@@ -146,7 +146,7 @@ int SVMCompiler::stack_size(ShaderSocketType type)
return size;
}
-int SVMCompiler::stack_find_offset(ShaderSocketType type)
+int SVMCompiler::stack_find_offset(SocketType::Type type)
{
int size = stack_size(type);
int offset = -1;
@@ -175,7 +175,7 @@ int SVMCompiler::stack_find_offset(ShaderSocketType type)
return 0;
}
-void SVMCompiler::stack_clear_offset(ShaderSocketType type, int offset)
+void SVMCompiler::stack_clear_offset(SocketType::Type type, int offset)
{
int size = stack_size(type);
@@ -193,22 +193,22 @@ int SVMCompiler::stack_assign(ShaderInput *input)
}
else {
/* not linked to output -> add nodes to load default value */
- input->stack_offset = stack_find_offset(input->type);
+ input->stack_offset = stack_find_offset(input->type());
- if(input->type == SHADER_SOCKET_FLOAT) {
- add_node(NODE_VALUE_F, __float_as_int(input->value.x), input->stack_offset);
+ if(input->type() == SocketType::FLOAT) {
+ add_node(NODE_VALUE_F, __float_as_int(input->value_float()), input->stack_offset);
}
- else if(input->type == SHADER_SOCKET_INT) {
- add_node(NODE_VALUE_F, (int)input->value.x, input->stack_offset);
+ else if(input->type() == SocketType::INT) {
+ add_node(NODE_VALUE_F, (int)input->value_float(), input->stack_offset);
}
- else if(input->type == SHADER_SOCKET_VECTOR ||
- input->type == SHADER_SOCKET_NORMAL ||
- input->type == SHADER_SOCKET_POINT ||
- input->type == SHADER_SOCKET_COLOR)
+ else if(input->type() == SocketType::VECTOR ||
+ input->type() == SocketType::NORMAL ||
+ input->type() == SocketType::POINT ||
+ input->type() == SocketType::COLOR)
{
add_node(NODE_VALUE_V, input->stack_offset);
- add_node(NODE_VALUE_V, input->value);
+ add_node(NODE_VALUE_V, input->value());
}
else /* should not get called for closure */
assert(0);
@@ -222,7 +222,7 @@ int SVMCompiler::stack_assign(ShaderOutput *output)
{
/* if no stack offset assigned yet, find one */
if(output->stack_offset == SVM_STACK_INVALID)
- output->stack_offset = stack_find_offset(output->type);
+ output->stack_offset = stack_find_offset(output->type());
return output->stack_offset;
}
@@ -247,11 +247,11 @@ void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output)
{
if(output->stack_offset == SVM_STACK_INVALID) {
assert(input->link);
- assert(stack_size(output->type) == stack_size(input->link->type));
+ assert(stack_size(output->type()) == stack_size(input->link->type()));
output->stack_offset = input->link->stack_offset;
- int size = stack_size(output->type);
+ int size = stack_size(output->type());
for(int i = 0; i < size; i++)
active_stack.users[output->stack_offset + i]++;
@@ -279,7 +279,7 @@ void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet& done)
all_done = false;
if(all_done) {
- stack_clear_offset(output->type, output->stack_offset);
+ stack_clear_offset(output->type(), output->stack_offset);
output->stack_offset = SVM_STACK_INVALID;
foreach(ShaderInput *in, output->links)
@@ -293,7 +293,7 @@ void SVMCompiler::stack_clear_temporary(ShaderNode *node)
{
foreach(ShaderInput *input, node->inputs) {
if(!input->link && input->stack_offset != SVM_STACK_INVALID) {
- stack_clear_offset(input->type, input->stack_offset);
+ stack_clear_offset(input->type(), input->stack_offset);
input->stack_offset = SVM_STACK_INVALID;
}
}
@@ -446,7 +446,7 @@ void SVMCompiler::generate_closure_node(ShaderNode *node,
const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight";
ShaderInput *weight_in = node->input(weight_name);
- if(weight_in && (weight_in->link || weight_in->value.x != 1.0f))
+ if(weight_in && (weight_in->link || weight_in->value_float() != 1.0f))
mix_weight_offset = stack_assign(weight_in);
else
mix_weight_offset = SVM_STACK_INVALID;
@@ -479,7 +479,7 @@ void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
}
else {
foreach(ShaderInput *in, node->inputs) {
- if(in->type == SHADER_SOCKET_CLOSURE && in->link)
+ if(in->type() == SocketType::CLOSURE && in->link)
generated_shared_closure_nodes(root_node,
in->link->parent,
state,
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index dbf1b1de947..e14d57d7601 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -99,8 +99,8 @@ public:
int stack_assign(ShaderInput *input);
int stack_assign_if_linked(ShaderInput *input);
int stack_assign_if_linked(ShaderOutput *output);
- int stack_find_offset(ShaderSocketType type);
- void stack_clear_offset(ShaderSocketType type, int offset);
+ int stack_find_offset(SocketType::Type type);
+ void stack_clear_offset(SocketType::Type type, int offset);
void stack_link(ShaderInput *input, ShaderOutput *output);
void add_node(ShaderNodeType type, int a = 0, int b = 0, int c = 0);
@@ -172,7 +172,7 @@ protected:
};
void stack_clear_temporary(ShaderNode *node);
- int stack_size(ShaderSocketType type);
+ int stack_size(SocketType::Type type);
void stack_clear_users(ShaderNode *node, ShaderNodeSet& done);
bool node_skip_input(ShaderNode *node, ShaderInput *input);
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index a5dfcd21ceb..8dba1379855 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -41,14 +41,14 @@ EdgeDice::EdgeDice(const SubdParams& params_)
}
}
-void EdgeDice::reserve(int num_verts, int num_tris)
+void EdgeDice::reserve(int num_verts)
{
Mesh *mesh = params.mesh;
vert_offset = mesh->verts.size();
tri_offset = mesh->triangles.size();
- mesh->reserve(vert_offset + num_verts, tri_offset + num_tris, 0, 0);
+ mesh->resize_mesh(vert_offset + num_verts, tri_offset);
Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
@@ -69,7 +69,7 @@ int EdgeDice::add_vert(Patch *patch, float2 uv)
if(params.ptex) {
Attribute *attr_ptex_uv = params.mesh->attributes.add(ATTR_STD_PTEX_UV);
- params.mesh->attributes.reserve();
+ params.mesh->attributes.resize();
float3 *ptex_uv = attr_ptex_uv->data_float3();
ptex_uv[vert_offset] = make_float3(uv.x, uv.y, 0.0f);
@@ -80,11 +80,17 @@ int EdgeDice::add_vert(Patch *patch, float2 uv)
void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2)
{
- params.mesh->add_triangle(v0, v1, v2, params.shader, params.smooth, false);
+ Mesh *mesh = params.mesh;
+
+ /* todo: optimize so we can reserve in advance, this is like push_back_slow() */
+ if(mesh->triangles.size() == mesh->triangles.capacity())
+ mesh->reserve_mesh(mesh->verts.size(), size_t(max(mesh->triangles.size() + 1, 1) * 1.2));
+
+ mesh->add_triangle(v0, v1, v2, params.shader, params.smooth, false);
if(params.ptex) {
Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
- params.mesh->attributes.reserve();
+ params.mesh->attributes.resize();
float *ptex_face_id = attr_ptex_face_id->data_float();
ptex_face_id[tri_offset] = (float)patch->ptex_face_id();
@@ -141,8 +147,7 @@ void QuadDice::reserve(EdgeFactors& ef, int Mu, int Mv)
{
/* XXX need to make this also work for edge factor 0 and 1 */
int num_verts = (ef.tu0 + ef.tu1 + ef.tv0 + ef.tv1) + (Mu - 1)*(Mv - 1);
- int num_tris = 0;
- EdgeDice::reserve(num_verts, num_tris);
+ EdgeDice::reserve(num_verts);
}
float2 QuadDice::map_uv(SubPatch& sub, float u, float v)
@@ -352,7 +357,7 @@ void TriangleDice::reserve(EdgeFactors& ef, int M)
if(!(M & 1))
num_verts++;
- EdgeDice::reserve(num_verts, 0);
+ EdgeDice::reserve(num_verts);
}
float2 TriangleDice::map_uv(SubPatch& sub, float2 uv)
diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h
index 49f786e949e..85bd0ea28f0 100644
--- a/intern/cycles/subd/subd_dice.h
+++ b/intern/cycles/subd/subd_dice.h
@@ -72,7 +72,7 @@ public:
explicit EdgeDice(const SubdParams& params);
- void reserve(int num_verts, int num_tris);
+ void reserve(int num_verts);
int add_vert(Patch *patch, float2 uv);
void add_triangle(Patch *patch, int v0, int v1, int v2);
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index b3a8c6d7c2e..e16a83d56d0 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -239,5 +239,45 @@ string string_to_ansi(const string& str)
#endif /* _WIN32 */
+string string_human_readable_size(size_t size)
+{
+ static const char suffixes[] = "BKMGTPEZY";
+
+ const char* suffix = suffixes;
+ size_t r = 0;
+
+ while(size >= 1024) {
+ r = size % 1024;
+ size /= 1024;
+ suffix++;
+ }
+
+ if(*suffix != 'B')
+ return string_printf("%.2f%c", double(size*1024+r)/1024.0, *suffix);
+ else
+ return string_printf("%zu", size);
+}
+
+string string_human_readable_number(size_t num)
+{
+ /* add thousands separators */
+ char buf[32];
+
+ char* p = buf+31;
+ *p = '\0';
+
+ int i = -1;
+ while(num) {
+ if(++i && i % 3 == 0)
+ *(--p) = ',';
+
+ *(--p) = '0' + (num % 10);
+
+ num /= 10;
+ }
+
+ return p;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h
index c4b51bda432..d3b5248c380 100644
--- a/intern/cycles/util/util_string.h
+++ b/intern/cycles/util/util_string.h
@@ -62,6 +62,11 @@ string string_from_wstring(const wstring& path);
string string_to_ansi(const string& str);
#endif
+/* Make a string from a size in bytes in human readable form */
+string string_human_readable_size(size_t size);
+/* Make a string from a unitless quantity in human readable form */
+string string_human_readable_number(size_t num);
+
CCL_NAMESPACE_END
#endif /* __UTIL_STRING_H__ */
diff --git a/intern/cycles/util/util_texture.h b/intern/cycles/util/util_texture.h
index 6da47858133..e00edc046f7 100644
--- a/intern/cycles/util/util_texture.h
+++ b/intern/cycles/util/util_texture.h
@@ -19,43 +19,47 @@
CCL_NAMESPACE_BEGIN
-/* Texture limits on various devices. */
+/* Texture limits on devices. */
/* CPU */
-#define TEX_NUM_BYTE4_IMAGES_CPU 1024
-#define TEX_NUM_FLOAT4_IMAGES_CPU 1024
-#define TEX_NUM_FLOAT_IMAGES_CPU 1024
-#define TEX_NUM_BYTE_IMAGES_CPU 1024
-#define TEX_IMAGE_BYTE4_START_CPU TEX_NUM_FLOAT4_IMAGES_CPU
-#define TEX_IMAGE_FLOAT_START_CPU (TEX_NUM_FLOAT4_IMAGES_CPU + TEX_NUM_BYTE4_IMAGES_CPU)
-#define TEX_IMAGE_BYTE_START_CPU (TEX_NUM_FLOAT4_IMAGES_CPU + TEX_NUM_BYTE4_IMAGES_CPU + TEX_NUM_BYTE_IMAGES_CPU)
+#define TEX_NUM_FLOAT4_CPU 1024
+#define TEX_NUM_BYTE4_CPU 1024
+#define TEX_NUM_FLOAT_CPU 1024
+#define TEX_NUM_BYTE_CPU 1024
+#define TEX_START_FLOAT4_CPU 0
+#define TEX_START_BYTE4_CPU TEX_NUM_FLOAT4_CPU
+#define TEX_START_FLOAT_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU)
+#define TEX_START_BYTE_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU + TEX_NUM_BYTE_CPU)
-/* CUDA (Fermi) */
-#define TEX_NUM_BYTE4_IMAGES_CUDA 88
-#define TEX_NUM_FLOAT4_IMAGES_CUDA 5
-#define TEX_NUM_FLOAT_IMAGES_CUDA 0
-#define TEX_NUM_BYTE_IMAGES_CUDA 0
-#define TEX_IMAGE_BYTE4_START_CUDA TEX_NUM_FLOAT4_IMAGES_CUDA
-#define TEX_IMAGE_FLOAT_START_CUDA (TEX_NUM_FLOAT4_IMAGES_CUDA + TEX_NUM_BYTE4_IMAGES_CUDA)
-#define TEX_IMAGE_BYTE_START_CUDA (TEX_NUM_FLOAT4_IMAGES_CUDA + TEX_NUM_BYTE4_IMAGES_CUDA + TEX_NUM_BYTE_IMAGES_CUDA)
+/* CUDA (Geforce 4xx and 5xx) */
+#define TEX_NUM_FLOAT4_CUDA 5
+#define TEX_NUM_BYTE4_CUDA 88
+#define TEX_NUM_FLOAT_CUDA 0
+#define TEX_NUM_BYTE_CUDA 0
+#define TEX_START_FLOAT4_CUDA 0
+#define TEX_START_BYTE4_CUDA TEX_NUM_FLOAT4_CUDA
+#define TEX_START_FLOAT_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA)
+#define TEX_START_BYTE_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA + TEX_NUM_BYTE_CUDA)
-/* CUDA (KEPLER and above) */
-#define TEX_NUM_BYTE4_IMAGES_CUDA_KEPLER 1024
-#define TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER 1024
-#define TEX_NUM_FLOAT_IMAGES_CUDA_KEPLER 1024
-#define TEX_NUM_BYTE_IMAGES_CUDA_KEPLER 1024
-#define TEX_IMAGE_BYTE4_START_CUDA_KEPLER TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER
-#define TEX_IMAGE_FLOAT_START_CUDA_KEPLER (TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER + TEX_NUM_BYTE4_IMAGES_CUDA_KEPLER)
-#define TEX_IMAGE_BYTE_START_CUDA_KEPLER (TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER + TEX_NUM_BYTE4_IMAGES_CUDA_KEPLER + TEX_NUM_BYTE_IMAGES_CUDA_KEPLER)
+/* CUDA (Kepler, Geforce 6xx and above) */
+#define TEX_NUM_FLOAT4_CUDA_KEPLER 1024
+#define TEX_NUM_BYTE4_CUDA_KEPLER 1024
+#define TEX_NUM_FLOAT_CUDA_KEPLER 1024
+#define TEX_NUM_BYTE_CUDA_KEPLER 1024
+#define TEX_START_FLOAT4_CUDA_KEPLER 0
+#define TEX_START_BYTE4_CUDA_KEPLER TEX_NUM_FLOAT4_CUDA_KEPLER
+#define TEX_START_FLOAT_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER)
+#define TEX_START_BYTE_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER + TEX_NUM_BYTE_CUDA_KEPLER)
/* OpenCL */
-#define TEX_NUM_BYTE4_IMAGES_OPENCL 1024
-#define TEX_NUM_FLOAT4_IMAGES_OPENCL 1024
-#define TEX_NUM_FLOAT_IMAGES_OPENCL 0
-#define TEX_NUM_BYTE_IMAGES_OPENCL 0
-#define TEX_IMAGE_BYTE4_START_OPENCL TEX_NUM_FLOAT4_IMAGES_OPENCL
-#define TEX_IMAGE_FLOAT_START_OPENCL (TEX_NUM_FLOAT4_IMAGES_OPENCL + TEX_NUM_BYTE4_IMAGES_OPENCL)
-#define TEX_IMAGE_BYTE_START_OPENCL (TEX_NUM_FLOAT4_IMAGES_OPENCL + TEX_NUM_BYTE4_IMAGES_OPENCL + TEX_NUM_BYTE_IMAGES_OPENCL)
+#define TEX_NUM_FLOAT4_OPENCL 1024
+#define TEX_NUM_BYTE4_OPENCL 1024
+#define TEX_NUM_FLOAT_OPENCL 0
+#define TEX_NUM_BYTE_OPENCL 0
+#define TEX_START_FLOAT4_OPENCL 0
+#define TEX_START_BYTE4_OPENCL TEX_NUM_FLOAT4_OPENCL
+#define TEX_START_FLOAT_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL)
+#define TEX_START_BYTE_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL + TEX_NUM_BYTE_OPENCL)
/* Color to use when textures are not found. */
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index 27285e49e9e..f18b7911f45 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -299,6 +299,12 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
m_buttonMask = 0x07C0F137;
m_hidMap = Modern3Dx_HID_map;
break;
+ case 0xC633:
+ puts("ndof: using SpaceMouse Enterprise");
+ m_deviceType = NDOF_SpaceMouseEnterprise;
+ m_buttonCount = 31;
+ m_hidMap = Modern3Dx_HID_map;
+ break;
default:
printf("ndof: unknown 3Dconnexion product %04hx\n", product_id);
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index ba82f37bb2a..d3c70bbac50 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -40,6 +40,7 @@ typedef enum {
NDOF_SpaceMousePro,
NDOF_SpaceMouseWireless,
NDOF_SpaceMouseProWireless,
+ NDOF_SpaceMouseEnterprise,
// older devices
NDOF_SpacePilot,
diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl
index 5921d6d9c73..853bf575582 100644
--- a/intern/opencolorio/gpu_shader_display_transform.glsl
+++ b/intern/opencolorio/gpu_shader_display_transform.glsl
@@ -38,7 +38,7 @@ float read_curve_mapping(int table, int index)
* But is it actually correct to subtract 1 here?
*/
float texture_index = float(index) / float(curve_mapping_lut_size - 1);
- return texture1D(curve_mapping_texture, texture_index) [table];
+ return texture1D(curve_mapping_texture, texture_index)[table];
}
float curvemap_calc_extend(int table, float x, vec2 first, vec2 last)
diff --git a/intern/opensubdiv/gpu_shader_opensubd_display.glsl b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
index 51e8ed46c34..a17dcef81c7 100644
--- a/intern/opensubdiv/gpu_shader_opensubd_display.glsl
+++ b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
@@ -111,7 +111,7 @@ void emit(int index, vec3 normal)
outpt.v.normal = normal;
/* TODO(sergey): Only uniform subdivisions atm. */
- vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
vec2 st = quadst[index];
INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
@@ -135,7 +135,7 @@ void emit(int index)
outpt.v.normal = inpt[index].v.normal;
/* TODO(sergey): Only uniform subdivisions atm. */
- vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
vec2 st = quadst[index];
INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
@@ -261,7 +261,7 @@ void main()
#else /* USE_COLOR_MATERIAL */
vec3 varying_position = inpt.v.position.xyz;
vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ?
- normalize(varying_position): vec3(0.0, 0.0, -1.0);
+ normalize(varying_position) : vec3(0.0, 0.0, -1.0);
for (int i = 0; i < num_enabled_lights; i++) {
/* todo: this is a slow check for disabled lights */
if (lightSource[i].specular.a == 0.0)
@@ -299,7 +299,7 @@ void main()
/* diffuse light */
vec3 light_diffuse = lightSource[i].diffuse.rgb;
float diffuse_bsdf = max(dot(N, light_direction), 0.0);
- L_diffuse += light_diffuse*diffuse_bsdf*intensity;
+ L_diffuse += light_diffuse * diffuse_bsdf * intensity;
/* specular light */
vec3 light_specular = lightSource[i].specular.rgb;
@@ -307,7 +307,7 @@ void main()
float specular_bsdf = pow(max(dot(N, H), 0.0),
gl_FrontMaterial.shininess);
- L_specular += light_specular*specular_bsdf * intensity;
+ L_specular += light_specular * specular_bsdf * intensity;
}
#endif /* USE_COLOR_MATERIAL */
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index c1a37d10961..d194de32bf3 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -408,6 +408,14 @@ class Mesh(bpy_types.ID):
the *vertices* argument. eg: [(5, 6, 8, 9), (1, 2, 3), ...]
:type faces: iterable object
+
+ .. warning::
+
+ Invalid mesh data
+ *(out of range indices, edges with matching indices,
+ 2 sided faces... etc)* are **not** prevented.
+ If the data used for mesh creation isn't known to be valid,
+ run :class:`Mesh.validate` after this function.
"""
from itertools import chain, islice, accumulate
diff --git a/release/scripts/presets/interface_theme/blender_24x.xml b/release/scripts/presets/interface_theme/blender_24x.xml
index 445c23b4c4e..ae42b605556 100644
--- a/release/scripts/presets/interface_theme/blender_24x.xml
+++ b/release/scripts/presets/interface_theme/blender_24x.xml
@@ -179,7 +179,7 @@
</wcol_tooltip>
<wcol_menu_item>
<ThemeWidgetColors outline="#000000"
- inner="#00000000"
+ inner="#d2d2d200"
inner_sel="#7f7f7fff"
item="#ffffffff"
text="#000000"
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index cdd16f26877..67fd1fddcac 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -698,7 +698,7 @@ kmi.properties.level = 5
km = kc.keymaps.new('Knife Tool Modal Map', space_type='EMPTY', region_type='WINDOW', modal=True)
kmi = km.keymap_items.new_modal('CANCEL', 'ESC', 'ANY', any=True)
-kmi = km.keymap_items.new_modal('ADD_CUT', 'LEFTMOUSE', 'ANY')
+kmi = km.keymap_items.new_modal('ADD_CUT', 'LEFTMOUSE', 'ANY', any=True)
kmi = km.keymap_items.new_modal('PANNING', 'LEFTMOUSE', 'ANY', alt=True)
kmi = km.keymap_items.new_modal('PANNING', 'MIDDLEMOUSE', 'ANY', alt=True)
kmi = km.keymap_items.new_modal('PANNING', 'RIGHTMOUSE', 'ANY', alt=True)
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 2b13a847e14..8ccc4a6eb0e 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -757,22 +757,22 @@ void DM_update_weight_mcol(
typedef struct DMVertexAttribs {
struct {
struct MLoopUV *array;
- int em_offset, gl_index, gl_texco;
+ int em_offset, gl_index, gl_texco, gl_info_index;
} tface[MAX_MTFACE];
struct {
struct MLoopCol *array;
- int em_offset, gl_index;
+ int em_offset, gl_index, gl_info_index;
} mcol[MAX_MCOL];
struct {
float (*array)[4];
- int em_offset, gl_index;
+ int em_offset, gl_index, gl_info_index;
} tang[MAX_MTFACE];
struct {
float (*array)[3];
- int em_offset, gl_index, gl_texco;
+ int em_offset, gl_index, gl_texco, gl_info_index;
} orco;
int tottface, totmcol, tottang, totorco;
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index bcc3b60b34e..d590a35bb57 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2003,15 +2003,10 @@ static void mesh_calc_modifiers(
DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
-#pragma omp parallel sections if (dm->numVertData + dm->numEdgeData + dm->numPolyData >= BKE_MESH_OMP_LIMIT)
- {
-#pragma omp section
- { range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0); }
-#pragma omp section
- { range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0); }
-#pragma omp section
- { range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0); }
- }
+ /* Not worth parallelizing this, gives less than 0.1% overall speedup in best of best cases... */
+ range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0);
+ range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0);
+ range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0);
}
}
@@ -3269,17 +3264,18 @@ void DM_calc_loop_tangents_step_0(
bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
char *ract_uv_name, char *rren_uv_name, char *rtangent_mask) {
/* Active uv in viewport */
+ int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV);
*ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV);
ract_uv_name[0] = 0;
if (*ract_uv_n != -1) {
- strcpy(ract_uv_name, loopData->layers[*ract_uv_n].name);
+ strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name);
}
/* Active tangent in render */
*rren_uv_n = CustomData_get_render_layer(loopData, CD_MLOOPUV);
rren_uv_name[0] = 0;
if (*rren_uv_n != -1) {
- strcpy(rren_uv_name, loopData->layers[*rren_uv_n].name);
+ strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name);
}
/* If active tangent not in tangent_names we take it into account */
@@ -3677,6 +3673,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
}
attribs->tface[a].gl_index = gattribs->layer[b].glindex;
+ attribs->tface[a].gl_info_index = gattribs->layer[b].glinfoindoex;
attribs->tface[a].gl_texco = gattribs->layer[b].gltexco;
}
else if (type == CD_MCOL) {
@@ -3700,6 +3697,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
}
attribs->mcol[a].gl_index = gattribs->layer[b].glindex;
+ attribs->mcol[a].gl_info_index = gattribs->layer[b].glinfoindoex;
}
else if (type == CD_TANGENT) {
/* note, even with 'is_editmesh' this uses the derived-meshes loop data */
@@ -3722,6 +3720,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
}
attribs->tang[a].gl_index = gattribs->layer[b].glindex;
+ attribs->tang[a].gl_info_index = gattribs->layer[b].glinfoindoex;
}
else if (type == CD_ORCO) {
/* original coordinates */
@@ -3741,6 +3740,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
attribs->orco.gl_index = gattribs->layer[b].glindex;
attribs->orco.gl_texco = gattribs->layer[b].gltexco;
+ attribs->orco.gl_info_index = gattribs->layer[b].glinfoindoex;
}
}
}
@@ -3769,6 +3769,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
glTexCoord3fv(orco);
else
glVertexAttrib3fv(attribs->orco.gl_index, orco);
+ glUniform1i(attribs->orco.gl_info_index, 0);
}
/* uv texture coordinates */
@@ -3787,6 +3788,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
glTexCoord2fv(uv);
else
glVertexAttrib2fv(attribs->tface[b].gl_index, uv);
+ glUniform1i(attribs->tface[b].gl_info_index, 0);
}
/* vertex colors */
@@ -3802,6 +3804,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
}
glVertexAttrib4fv(attribs->mcol[b].gl_index, col);
+ glUniform1i(attribs->mcol[b].gl_info_index, GPU_ATTR_INFO_SRGB);
}
/* tangent for normal mapping */
@@ -3811,6 +3814,7 @@ void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert,
const float *tang = (array) ? array[a * 4 + vert] : zero;
glVertexAttrib4fv(attribs->tang[b].gl_index, tang);
}
+ glUniform1i(attribs->tang[b].gl_info_index, 0);
}
}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 9c163990dd2..249e4ccd89c 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -1020,6 +1020,7 @@ static void cdDM_drawMappedFacesGLSL(
if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) {
matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index;
+ matconv[a].datatypes[numdata].info_index = matconv[a].attribs.orco.gl_info_index;
matconv[a].datatypes[numdata].size = 3;
matconv[a].datatypes[numdata].type = GL_FLOAT;
numdata++;
@@ -1027,6 +1028,7 @@ static void cdDM_drawMappedFacesGLSL(
for (b = 0; b < matconv[a].attribs.tottface; b++) {
if (matconv[a].attribs.tface[b].array) {
matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index;
+ matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tface[b].gl_info_index;
matconv[a].datatypes[numdata].size = 2;
matconv[a].datatypes[numdata].type = GL_FLOAT;
numdata++;
@@ -1035,6 +1037,7 @@ static void cdDM_drawMappedFacesGLSL(
for (b = 0; b < matconv[a].attribs.totmcol; b++) {
if (matconv[a].attribs.mcol[b].array) {
matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index;
+ matconv[a].datatypes[numdata].info_index = matconv[a].attribs.mcol[b].gl_info_index;
matconv[a].datatypes[numdata].size = 4;
matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE;
numdata++;
@@ -1043,6 +1046,7 @@ static void cdDM_drawMappedFacesGLSL(
for (b = 0; b < matconv[a].attribs.tottang; b++) {
if (matconv[a].attribs.tang[b].array) {
matconv[a].datatypes[numdata].index = matconv[a].attribs.tang[b].gl_index;
+ matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tang[b].gl_info_index;
matconv[a].datatypes[numdata].size = 4;
matconv[a].datatypes[numdata].type = GL_FLOAT;
numdata++;
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index bac59c8c62d..c1f1f0128f5 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -43,6 +43,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "BKE_colortools.h"
@@ -53,10 +54,6 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
-#ifdef _OPENMP
-# include <omp.h>
-#endif
-
/* ********************************* color curve ********************* */
/* ***************** operations on full struct ************* */
@@ -1089,31 +1086,170 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM
}
/* if view_settings, it also applies this to byte buffers */
+typedef struct ScopesUpdateData {
+ Scopes *scopes;
+ const ImBuf *ibuf;
+ struct ColormanageProcessor *cm_processor;
+ const unsigned char *display_buffer;
+ const int ycc_mode;
+
+ unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a;
+} ScopesUpdateData;
+
+typedef struct ScopesUpdateDataChunk {
+ unsigned int bin_lum[256];
+ unsigned int bin_r[256];
+ unsigned int bin_g[256];
+ unsigned int bin_b[256];
+ unsigned int bin_a[256];
+ float min[3], max[3];
+} ScopesUpdateDataChunk;
+
+static void scopes_update_cb(void *userdata, void *userdata_chunk, const int y, const int UNUSED(threadid))
+{
+ const ScopesUpdateData *data = userdata;
+
+ Scopes *scopes = data->scopes;
+ const ImBuf *ibuf = data->ibuf;
+ struct ColormanageProcessor *cm_processor = data->cm_processor;
+ const unsigned char *display_buffer = data->display_buffer;
+ const int ycc_mode = data->ycc_mode;
+
+ ScopesUpdateDataChunk *data_chunk = userdata_chunk;
+ unsigned int *bin_lum = data_chunk->bin_lum;
+ unsigned int *bin_r = data_chunk->bin_r;
+ unsigned int *bin_g = data_chunk->bin_g;
+ unsigned int *bin_b = data_chunk->bin_b;
+ unsigned int *bin_a = data_chunk->bin_a;
+ float *min = data_chunk->min;
+ float *max = data_chunk->max;
+
+ const float *rf = NULL;
+ const unsigned char *rc = NULL;
+ const int rows_per_sample_line = ibuf->y / scopes->sample_lines;
+ const int savedlines = y / rows_per_sample_line;
+ const bool do_sample_line = (savedlines < scopes->sample_lines) && (y % rows_per_sample_line) == 0;
+ const bool is_float = (ibuf->rect_float != NULL);
+
+ if (is_float)
+ rf = ibuf->rect_float + ((size_t)y) * ibuf->x * ibuf->channels;
+ else {
+ rc = display_buffer + ((size_t)y) * ibuf->x * ibuf->channels;
+ }
+
+ for (int x = 0; x < ibuf->x; x++) {
+ float rgba[4], ycc[3], luma;
+
+ if (is_float) {
+ switch (ibuf->channels) {
+ case 4:
+ copy_v4_v4(rgba, rf);
+ IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
+ break;
+ case 3:
+ copy_v3_v3(rgba, rf);
+ IMB_colormanagement_processor_apply_v3(cm_processor, rgba);
+ rgba[3] = 1.0f;
+ break;
+ case 2:
+ copy_v3_fl(rgba, rf[0]);
+ rgba[3] = rf[1];
+ break;
+ case 1:
+ copy_v3_fl(rgba, rf[0]);
+ rgba[3] = 1.0f;
+ break;
+ default:
+ BLI_assert(0);
+ }
+ }
+ else {
+ for (int c = 4; c--;)
+ rgba[c] = rc[c] * INV_255;
+ }
+
+ /* we still need luma for histogram */
+ luma = IMB_colormanagement_get_luminance(rgba);
+
+ /* check for min max */
+ if (ycc_mode == -1) {
+ minmax_v3v3_v3(min, max, rgba);
+ }
+ else {
+ rgb_to_ycc(rgba[0], rgba[1], rgba[2], &ycc[0], &ycc[1], &ycc[2], ycc_mode);
+ mul_v3_fl(ycc, INV_255);
+ minmax_v3v3_v3(min, max, ycc);
+ }
+ /* increment count for histo*/
+ bin_lum[get_bin_float(luma)]++;
+ bin_r[get_bin_float(rgba[0])]++;
+ bin_g[get_bin_float(rgba[1])]++;
+ bin_b[get_bin_float(rgba[2])]++;
+ bin_a[get_bin_float(rgba[3])]++;
+
+ /* save sample if needed */
+ if (do_sample_line) {
+ const float fx = (float)x / (float)ibuf->x;
+ const int idx = 2 * (ibuf->x * savedlines + x);
+ save_sample_line(scopes, idx, fx, rgba, ycc);
+ }
+
+ rf += ibuf->channels;
+ rc += ibuf->channels;
+ }
+}
+
+static void scopes_update_finalize(void *userdata, void *userdata_chunk)
+{
+ const ScopesUpdateData *data = userdata;
+ const ScopesUpdateDataChunk *data_chunk = userdata_chunk;
+
+ unsigned int *bin_lum = data->bin_lum;
+ unsigned int *bin_r = data->bin_r;
+ unsigned int *bin_g = data->bin_g;
+ unsigned int *bin_b = data->bin_b;
+ unsigned int *bin_a = data->bin_a;
+ const unsigned int *bin_lum_c = data_chunk->bin_lum;
+ const unsigned int *bin_r_c = data_chunk->bin_r;
+ const unsigned int *bin_g_c = data_chunk->bin_g;
+ const unsigned int *bin_b_c = data_chunk->bin_b;
+ const unsigned int *bin_a_c = data_chunk->bin_a;
+
+ float (*minmax)[2] = data->scopes->minmax;
+ const float *min = data_chunk->min;
+ const float *max = data_chunk->max;
+
+ for (int b = 256; b--;) {
+ bin_lum[b] += bin_lum_c[b];
+ bin_r[b] += bin_r_c[b];
+ bin_g[b] += bin_g_c[b];
+ bin_b[b] += bin_b_c[b];
+ bin_a[b] += bin_a_c[b];
+ }
+
+ for (int c = 3; c--;) {
+ if (min[c] < minmax[c][0])
+ minmax[c][0] = min[c];
+ if (max[c] > minmax[c][1])
+ minmax[c][1] = max[c];
+ }
+}
+
void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings,
const ColorManagedDisplaySettings *display_settings)
{
-#ifdef _OPENMP
- const int num_threads = BLI_system_thread_count();
-#endif
- int a, y;
+ int a;
unsigned int nl, na, nr, ng, nb;
double divl, diva, divr, divg, divb;
- unsigned char *display_buffer;
+ const unsigned char *display_buffer = NULL;
unsigned int bin_lum[256] = {0},
bin_r[256] = {0},
bin_g[256] = {0},
bin_b[256] = {0},
bin_a[256] = {0};
- unsigned int bin_lum_t[BLENDER_MAX_THREADS][256] = {{0}},
- bin_r_t[BLENDER_MAX_THREADS][256] = {{0}},
- bin_g_t[BLENDER_MAX_THREADS][256] = {{0}},
- bin_b_t[BLENDER_MAX_THREADS][256] = {{0}},
- bin_a_t[BLENDER_MAX_THREADS][256] = {{0}};
int ycc_mode = -1;
- const bool is_float = (ibuf->rect_float != NULL);
void *cache_handle = NULL;
struct ColormanageProcessor *cm_processor = NULL;
- int rows_per_sample_line;
if (ibuf->rect == NULL && ibuf->rect_float == NULL) return;
@@ -1151,7 +1287,6 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
scopes->sample_lines = ibuf->y;
/* scan the image */
- rows_per_sample_line = ibuf->y / scopes->sample_lines;
for (a = 0; a < 3; a++) {
scopes->minmax[a][0] = 25500.0f;
scopes->minmax[a][1] = -25500.0f;
@@ -1177,129 +1312,21 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *
cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
}
else {
- display_buffer = (unsigned char *)IMB_display_buffer_acquire(ibuf,
- view_settings,
- display_settings,
- &cache_handle);
+ display_buffer = (const unsigned char *)IMB_display_buffer_acquire(
+ ibuf, view_settings, display_settings, &cache_handle);
}
/* Keep number of threads in sync with the merge parts below. */
-#pragma omp parallel for private(y) schedule(static) num_threads(num_threads) if (ibuf->y > 256)
- for (y = 0; y < ibuf->y; y++) {
-#ifdef _OPENMP
- const int thread_idx = omp_get_thread_num();
-#else
- const int thread_idx = 0;
-#endif
- const float *rf = NULL;
- const unsigned char *rc = NULL;
- const int savedlines = y / rows_per_sample_line;
- const bool do_sample_line = (savedlines < scopes->sample_lines) && (y % rows_per_sample_line) == 0;
- float min[3] = { FLT_MAX, FLT_MAX, FLT_MAX},
- max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
- int x, c;
- if (is_float)
- rf = ibuf->rect_float + ((size_t)y) * ibuf->x * ibuf->channels;
- else {
- rc = display_buffer + ((size_t)y) * ibuf->x * ibuf->channels;
- }
- for (x = 0; x < ibuf->x; x++) {
- float rgba[4], ycc[3], luma;
- if (is_float) {
-
- switch (ibuf->channels) {
- case 4:
- copy_v4_v4(rgba, rf);
- IMB_colormanagement_processor_apply_v4(cm_processor, rgba);
- break;
- case 3:
- copy_v3_v3(rgba, rf);
- IMB_colormanagement_processor_apply_v3(cm_processor, rgba);
- rgba[3] = 1.0f;
- break;
- case 2:
- copy_v3_fl(rgba, rf[0]);
- rgba[3] = rf[1];
- break;
- case 1:
- copy_v3_fl(rgba, rf[0]);
- rgba[3] = 1.0f;
- break;
- default:
- BLI_assert(0);
- }
- }
- else {
- for (c = 0; c < 4; c++)
- rgba[c] = rc[c] * INV_255;
- }
-
- /* we still need luma for histogram */
- luma = IMB_colormanagement_get_luminance(rgba);
-
- /* check for min max */
- if (ycc_mode == -1) {
- for (c = 0; c < 3; c++) {
- if (rgba[c] < min[c]) min[c] = rgba[c];
- if (rgba[c] > max[c]) max[c] = rgba[c];
- }
- }
- else {
- rgb_to_ycc(rgba[0], rgba[1], rgba[2], &ycc[0], &ycc[1], &ycc[2], ycc_mode);
- for (c = 0; c < 3; c++) {
- ycc[c] *= INV_255;
- if (ycc[c] < min[c]) min[c] = ycc[c];
- if (ycc[c] > max[c]) max[c] = ycc[c];
- }
- }
- /* increment count for histo*/
- bin_lum_t[thread_idx][get_bin_float(luma)] += 1;
- bin_r_t[thread_idx][get_bin_float(rgba[0])] += 1;
- bin_g_t[thread_idx][get_bin_float(rgba[1])] += 1;
- bin_b_t[thread_idx][get_bin_float(rgba[2])] += 1;
- bin_a_t[thread_idx][get_bin_float(rgba[3])] += 1;
-
- /* save sample if needed */
- if (do_sample_line) {
- const float fx = (float)x / (float)ibuf->x;
- const int idx = 2 * (ibuf->x * savedlines + x);
- save_sample_line(scopes, idx, fx, rgba, ycc);
- }
-
- rf += ibuf->channels;
- rc += ibuf->channels;
- }
-#pragma omp critical
- {
- for (c = 0; c < 3; c++) {
- if (min[c] < scopes->minmax[c][0]) scopes->minmax[c][0] = min[c];
- if (max[c] > scopes->minmax[c][1]) scopes->minmax[c][1] = max[c];
- }
- }
- }
-
-#ifdef _OPENMP
- if (ibuf->y > 256) {
- for (a = 0; a < num_threads; a++) {
- int b;
- for (b = 0; b < 256; b++) {
- bin_lum[b] += bin_lum_t[a][b];
- bin_r[b] += bin_r_t[a][b];
- bin_g[b] += bin_g_t[a][b];
- bin_b[b] += bin_b_t[a][b];
- bin_a[b] += bin_a_t[a][b];
- }
- }
- }
- else
-#endif
- {
- memcpy(bin_lum, bin_lum_t[0], sizeof(bin_lum));
- memcpy(bin_r, bin_r_t[0], sizeof(bin_r));
- memcpy(bin_g, bin_g_t[0], sizeof(bin_g));
- memcpy(bin_b, bin_b_t[0], sizeof(bin_b));
- memcpy(bin_a, bin_a_t[0], sizeof(bin_a));
- }
+ ScopesUpdateData data = {
+ .scopes = scopes, . ibuf = ibuf,
+ .cm_processor = cm_processor, .display_buffer = display_buffer, .ycc_mode = ycc_mode,
+ .bin_lum = bin_lum, .bin_r = bin_r, .bin_g = bin_g, .bin_b = bin_b, .bin_a = bin_a,
+ };
+ ScopesUpdateDataChunk data_chunk = {0};
+ INIT_MINMAX(data_chunk.min, data_chunk.max);
+
+ BLI_task_parallel_range_finalize(0, ibuf->y, &data, &data_chunk, sizeof(data_chunk),
+ scopes_update_cb, scopes_update_finalize, ibuf->y > 256, false);
/* test for nicer distribution even - non standard, leave it out for a while */
#if 0
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index e57e9ffcd66..5fba6c253a3 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -57,6 +57,7 @@
#include "MEM_guardedalloc.h"
#include "GPU_glew.h"
+#include "GPU_buffers.h"
#include "GPU_shader.h"
#include "GPU_basic_shader.h"
@@ -1427,6 +1428,7 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
glTexCoord3fv(orco);
else
glVertexAttrib3fv(attribs->orco.gl_index, orco);
+ glUniform1i(attribs->orco.gl_info_index, 0);
}
for (i = 0; i < attribs->tottface; i++) {
const float *uv;
@@ -1443,17 +1445,19 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
glTexCoord2fv(uv);
else
glVertexAttrib2fv(attribs->tface[i].gl_index, uv);
+ glUniform1i(attribs->tface[i].gl_info_index, 0);
}
for (i = 0; i < attribs->totmcol; i++) {
- GLubyte col[4];
+ float col[4];
if (attribs->mcol[i].em_offset != -1) {
const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset);
- copy_v4_v4_uchar(col, &cp->r);
+ rgba_uchar_to_float(col, &cp->r);
}
else {
- col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0;
+ col[0] = 0.0f; col[1] = 0.0f; col[2] = 0.0f; col[3] = 0.0f;
}
- glVertexAttrib4ubv(attribs->mcol[i].gl_index, col);
+ glVertexAttrib4fv(attribs->mcol[i].gl_index, col);
+ glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
}
for (i = 0; i < attribs->tottang; i++) {
@@ -1465,6 +1469,7 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
tang = zero;
}
glVertexAttrib4fv(attribs->tang[i].gl_index, tang);
+ glUniform1i(attribs->tang[i].gl_info_index, 0);
}
}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 1ae7ca189fb..0b2c844cb2c 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -109,8 +109,8 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
#define IMA_NO_INDEX 0x7FEFEFEF
/* quick lookup: supports 1 million frames, thousand passes */
-#define IMA_MAKE_INDEX(frame, index) ((frame) << 10) + index
-#define IMA_INDEX_FRAME(index) (index >> 10)
+#define IMA_MAKE_INDEX(frame, index) (((frame) << 10) + (index))
+#define IMA_INDEX_FRAME(index) ((index) >> 10)
/*
#define IMA_INDEX_PASS(index) (index & ~1023)
*/
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 1fec725dbb7..30f82a50ed9 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -1148,7 +1148,6 @@ static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode
/* parses the geom+tex nodes */
ntreeShaderGetTexcoMode(ntree, r_mode, &basemat->texco, &basemat->mode_l);
- basemat->nmap_tangent_names_count = 0;
for (node = ntree->nodes.first; node; node = node->next) {
if (node->id) {
if (GS(node->id->name) == ID_MA) {
@@ -1199,7 +1198,7 @@ void init_render_material(Material *mat, int r_mode, float *amb)
* mode_l will have it set when all node materials are shadeless. */
mat->mode_l = (mat->mode & MA_MODE_PIPELINE) | MA_SHLESS;
mat->mode2_l = mat->mode2 & MA_MODE2_PIPELINE;
-
+ mat->nmap_tangent_names_count = 0;
init_render_nodetree(mat->nodetree, mat, r_mode, amb);
if (!mat->nodetree->execdata)
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index e855f6faa22..518d8d68919 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -44,6 +44,7 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_task.h"
#include "BKE_shrinkwrap.h"
#include "BKE_DerivedMesh.h"
@@ -58,7 +59,7 @@
/* for timing... */
#if 0
-# include "PIL_time.h"
+# include "PIL_time_utildefines.h"
#else
# define TIMEIT_BENCH(expr, id) (expr)
#endif
@@ -66,16 +67,88 @@
/* Util macros */
#define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n"))
+typedef struct ShrinkwrapCalcCBData {
+ ShrinkwrapCalcData *calc;
+
+ void *treeData;
+ void *auxData;
+ BVHTree *targ_tree;
+ BVHTree *aux_tree;
+ void *targ_callback;
+ void *aux_callback;
+
+ float *proj_axis;
+ SpaceTransform *local2aux;
+} ShrinkwrapCalcCBData;
+
/*
* Shrinkwrap to the nearest vertex
*
* it builds a kdtree of vertexs we can attach to and then
* for each vertex performs a nearest vertex search on the tree
*/
-static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
+static void shrinkwrap_calc_nearest_vertex_cb_ex(
+ void *userdata, void *userdata_chunk, const int i, const int UNUSED(threadid))
{
- int i;
+ ShrinkwrapCalcCBData *data = userdata;
+
+ ShrinkwrapCalcData *calc = data->calc;
+ BVHTreeFromMesh *treeData = data->treeData;
+ BVHTreeNearest *nearest = userdata_chunk;
+
+ float *co = calc->vertexCos[i];
+ float tmp_co[3];
+ float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
+
+ if (calc->invert_vgroup) {
+ weight = 1.0f - weight;
+ }
+
+ if (weight == 0.0f) {
+ return;
+ }
+
+ /* Convert the vertex to tree coordinates */
+ if (calc->vert) {
+ copy_v3_v3(tmp_co, calc->vert[i].co);
+ }
+ else {
+ copy_v3_v3(tmp_co, co);
+ }
+ BLI_space_transform_apply(&calc->local2target, tmp_co);
+
+ /* Use local proximity heuristics (to reduce the nearest search)
+ *
+ * If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex
+ * so we can initiate the "nearest.dist" with the expected value to that last hit.
+ * This will lead in pruning of the search tree. */
+ if (nearest->index != -1)
+ nearest->dist_sq = len_squared_v3v3(tmp_co, nearest->co);
+ else
+ nearest->dist_sq = FLT_MAX;
+
+ BLI_bvhtree_find_nearest(treeData->tree, tmp_co, nearest, treeData->nearest_callback, treeData);
+
+
+ /* Found the nearest vertex */
+ if (nearest->index != -1) {
+ /* Adjusting the vertex weight,
+ * so that after interpolating it keeps a certain distance from the nearest position */
+ if (nearest->dist_sq > FLT_EPSILON) {
+ const float dist = sqrtf(nearest->dist_sq);
+ weight *= (dist - calc->keepDist) / dist;
+ }
+
+ /* Convert the coordinates back to mesh coordinates */
+ copy_v3_v3(tmp_co, nearest->co);
+ BLI_space_transform_invert(&calc->local2target, tmp_co);
+
+ interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
+ }
+}
+static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
+{
BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
BVHTreeNearest nearest = NULL_BVHTreeNearest;
@@ -89,61 +162,11 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
/* Setup nearest */
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
-#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(treeData, calc) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT)
-#endif
- for (i = 0; i < calc->numVerts; ++i) {
- float *co = calc->vertexCos[i];
- float tmp_co[3];
- float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
-
- if (calc->invert_vgroup) {
- weight = 1.0f - weight;
- }
-
- if (weight == 0.0f) {
- continue;
- }
-
-
- /* Convert the vertex to tree coordinates */
- if (calc->vert) {
- copy_v3_v3(tmp_co, calc->vert[i].co);
- }
- else {
- copy_v3_v3(tmp_co, co);
- }
- BLI_space_transform_apply(&calc->local2target, tmp_co);
-
- /* Use local proximity heuristics (to reduce the nearest search)
- *
- * If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex
- * so we can initiate the "nearest.dist" with the expected value to that last hit.
- * This will lead in pruning of the search tree. */
- if (nearest.index != -1)
- nearest.dist_sq = len_squared_v3v3(tmp_co, nearest.co);
- else
- nearest.dist_sq = FLT_MAX;
-
- BLI_bvhtree_find_nearest(treeData.tree, tmp_co, &nearest, treeData.nearest_callback, &treeData);
-
-
- /* Found the nearest vertex */
- if (nearest.index != -1) {
- /* Adjusting the vertex weight,
- * so that after interpolating it keeps a certain distance from the nearest position */
- if (nearest.dist_sq > FLT_EPSILON) {
- const float dist = sqrtf(nearest.dist_sq);
- weight *= (dist - calc->keepDist) / dist;
- }
- /* Convert the coordinates back to mesh coordinates */
- copy_v3_v3(tmp_co, nearest.co);
- BLI_space_transform_invert(&calc->local2target, tmp_co);
-
- interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
- }
- }
+ ShrinkwrapCalcCBData data = {.calc = calc, .treeData = &treeData};
+ BLI_task_parallel_range_ex(
+ 0, calc->numVerts, &data, &nearest, sizeof(nearest), shrinkwrap_calc_nearest_vertex_cb_ex,
+ calc->numVerts > BKE_MESH_OMP_LIMIT, false);
free_bvhtree_from_mesh(&treeData);
}
@@ -230,13 +253,109 @@ bool BKE_shrinkwrap_project_normal(
return false;
}
+static void shrinkwrap_calc_normal_projection_cb_ex(
+ void *userdata, void *userdata_chunk, const int i, const int UNUSED(threadid))
+{
+ ShrinkwrapCalcCBData *data = userdata;
+
+ ShrinkwrapCalcData *calc = data->calc;
+ void *treeData = data->treeData;
+ void *auxData = data->auxData;
+ BVHTree *targ_tree = data->targ_tree;
+ BVHTree *aux_tree = data->aux_tree;
+ void *targ_callback = data->targ_callback;
+ void *aux_callback = data->aux_callback;
+
+ float *proj_axis = data->proj_axis;
+ SpaceTransform *local2aux = data->local2aux;
+
+ BVHTreeRayHit *hit = userdata_chunk;
+
+ const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit;
+ float *co = calc->vertexCos[i];
+ float tmp_co[3], tmp_no[3];
+ float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
+
+ if (calc->invert_vgroup) {
+ weight = 1.0f - weight;
+ }
+
+ if (weight == 0.0f) {
+ return;
+ }
+
+ if (calc->vert) {
+ /* calc->vert contains verts from derivedMesh */
+ /* this coordinated are deformed by vertexCos only for normal projection (to get correct normals) */
+ /* for other cases calc->varts contains undeformed coordinates and vertexCos should be used */
+ if (calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) {
+ copy_v3_v3(tmp_co, calc->vert[i].co);
+ normal_short_to_float_v3(tmp_no, calc->vert[i].no);
+ }
+ else {
+ copy_v3_v3(tmp_co, co);
+ copy_v3_v3(tmp_no, proj_axis);
+ }
+ }
+ else {
+ copy_v3_v3(tmp_co, co);
+ copy_v3_v3(tmp_no, proj_axis);
+ }
+
+
+ hit->index = -1;
+ hit->dist = BVH_RAYCAST_DIST_MAX; /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */
+
+ /* Project over positive direction of axis */
+ if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR) {
+ if (aux_tree) {
+ BKE_shrinkwrap_project_normal(
+ 0, tmp_co, tmp_no,
+ local2aux, aux_tree, hit,
+ aux_callback, auxData);
+ }
+
+ BKE_shrinkwrap_project_normal(
+ calc->smd->shrinkOpts, tmp_co, tmp_no,
+ &calc->local2target, targ_tree, hit,
+ targ_callback, treeData);
+ }
+
+ /* Project over negative direction of axis */
+ if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR) {
+ float inv_no[3];
+ negate_v3_v3(inv_no, tmp_no);
+
+ if (aux_tree) {
+ BKE_shrinkwrap_project_normal(
+ 0, tmp_co, inv_no,
+ local2aux, aux_tree, hit,
+ aux_callback, auxData);
+ }
+
+ BKE_shrinkwrap_project_normal(
+ calc->smd->shrinkOpts, tmp_co, inv_no,
+ &calc->local2target, targ_tree, hit,
+ targ_callback, treeData);
+ }
+
+ /* don't set the initial dist (which is more efficient),
+ * because its calculated in the targets space, we want the dist in our own space */
+ if (proj_limit_squared != 0.0f) {
+ if (len_squared_v3v3(hit->co, co) > proj_limit_squared) {
+ hit->index = -1;
+ }
+ }
+
+ if (hit->index != -1) {
+ madd_v3_v3v3fl(hit->co, hit->co, tmp_no, calc->keepDist);
+ interp_v3_v3v3(co, co, hit->co, weight);
+ }
+}
static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for_render)
{
- int i;
-
/* Options about projection direction */
- const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit;
float proj_axis[3] = {0.0f, 0.0f, 0.0f};
/* Raycast and tree stuff */
@@ -305,7 +424,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
}
if (targ_tree) {
BVHTree *aux_tree = NULL;
- void *aux_callback;
+ void *aux_callback = NULL;
if (auxMesh != NULL) {
/* use editmesh to avoid array allocation */
if (calc->smd->auxTarget && auxMesh->type == DM_TYPE_EDITBMESH) {
@@ -316,99 +435,22 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
}
}
else {
- if ((aux_tree = bvhtree_from_mesh_looptri(&dmauxdata_stack, calc->target, 0.0, 4, 6)) != NULL) {
+ if ((aux_tree = bvhtree_from_mesh_looptri(&dmauxdata_stack, auxMesh, 0.0, 4, 6)) != NULL) {
aux_callback = dmauxdata_stack.raycast_callback;
auxData = &dmauxdata_stack;
}
}
}
/* After sucessufuly build the trees, start projection vertexs */
-
-#ifndef __APPLE__
-#pragma omp parallel for private(i, hit) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT)
-#endif
- for (i = 0; i < calc->numVerts; ++i) {
- float *co = calc->vertexCos[i];
- float tmp_co[3], tmp_no[3];
- float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
-
- if (calc->invert_vgroup) {
- weight = 1.0f - weight;
- }
-
- if (weight == 0.0f) {
- continue;
- }
-
- if (calc->vert) {
- /* calc->vert contains verts from derivedMesh */
- /* this coordinated are deformed by vertexCos only for normal projection (to get correct normals) */
- /* for other cases calc->varts contains undeformed coordinates and vertexCos should be used */
- if (calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) {
- copy_v3_v3(tmp_co, calc->vert[i].co);
- normal_short_to_float_v3(tmp_no, calc->vert[i].no);
- }
- else {
- copy_v3_v3(tmp_co, co);
- copy_v3_v3(tmp_no, proj_axis);
- }
- }
- else {
- copy_v3_v3(tmp_co, co);
- copy_v3_v3(tmp_no, proj_axis);
- }
-
-
- hit.index = -1;
- hit.dist = BVH_RAYCAST_DIST_MAX; /* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */
-
- /* Project over positive direction of axis */
- if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR) {
-
- if (aux_tree) {
- BKE_shrinkwrap_project_normal(
- 0, tmp_co, tmp_no,
- &local2aux, aux_tree, &hit,
- aux_callback, auxData);
- }
-
- BKE_shrinkwrap_project_normal(
- calc->smd->shrinkOpts, tmp_co, tmp_no,
- &calc->local2target, targ_tree, &hit,
- targ_callback, treeData);
- }
-
- /* Project over negative direction of axis */
- if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR) {
- float inv_no[3];
- negate_v3_v3(inv_no, tmp_no);
-
- if (aux_tree) {
- BKE_shrinkwrap_project_normal(
- 0, tmp_co, inv_no,
- &local2aux, aux_tree, &hit,
- aux_callback, auxData);
- }
-
- BKE_shrinkwrap_project_normal(
- calc->smd->shrinkOpts, tmp_co, inv_no,
- &calc->local2target, targ_tree, &hit,
- targ_callback, treeData);
- }
-
- /* don't set the initial dist (which is more efficient),
- * because its calculated in the targets space, we want the dist in our own space */
- if (proj_limit_squared != 0.0f) {
- if (len_squared_v3v3(hit.co, co) > proj_limit_squared) {
- hit.index = -1;
- }
- }
-
- if (hit.index != -1) {
- madd_v3_v3v3fl(hit.co, hit.co, tmp_no, calc->keepDist);
- interp_v3_v3v3(co, co, hit.co, weight);
- }
- }
+ ShrinkwrapCalcCBData data = {
+ .calc = calc,
+ .treeData = treeData, .targ_tree = targ_tree, .targ_callback = targ_callback,
+ .auxData = auxData, .aux_tree = aux_tree, .aux_callback = aux_callback,
+ .proj_axis = proj_axis, .local2aux = &local2aux,
+ };
+ BLI_task_parallel_range_ex(
+ 0, calc->numVerts, &data, &hit, sizeof(hit), shrinkwrap_calc_normal_projection_cb_ex,
+ calc->numVerts > BKE_MESH_OMP_LIMIT, false);
}
/* free data structures */
@@ -428,10 +470,75 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
* it builds a BVHTree from the target mesh and then performs a
* NN matches for each vertex
*/
-static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
+static void shrinkwrap_calc_nearest_surface_point_cb_ex(
+ void *userdata, void *userdata_chunk, const int i, const int UNUSED(threadid))
{
- int i;
+ ShrinkwrapCalcCBData *data = userdata;
+
+ ShrinkwrapCalcData *calc = data->calc;
+ BVHTreeFromMesh *treeData = data->treeData;
+ BVHTreeNearest *nearest = userdata_chunk;
+
+ float *co = calc->vertexCos[i];
+ float tmp_co[3];
+ float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
+
+ if (calc->invert_vgroup) {
+ weight = 1.0f - weight;
+ }
+
+ if (weight == 0.0f) {
+ return;
+ }
+
+ /* Convert the vertex to tree coordinates */
+ if (calc->vert) {
+ copy_v3_v3(tmp_co, calc->vert[i].co);
+ }
+ else {
+ copy_v3_v3(tmp_co, co);
+ }
+ BLI_space_transform_apply(&calc->local2target, tmp_co);
+
+ /* Use local proximity heuristics (to reduce the nearest search)
+ *
+ * If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex
+ * so we can initiate the "nearest.dist" with the expected value to that last hit.
+ * This will lead in pruning of the search tree. */
+ if (nearest->index != -1)
+ nearest->dist_sq = len_squared_v3v3(tmp_co, nearest->co);
+ else
+ nearest->dist_sq = FLT_MAX;
+
+ BLI_bvhtree_find_nearest(treeData->tree, tmp_co, nearest, treeData->nearest_callback, treeData);
+
+ /* Found the nearest vertex */
+ if (nearest->index != -1) {
+ if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE) {
+ /* Make the vertex stay on the front side of the face */
+ madd_v3_v3v3fl(tmp_co, nearest->co, nearest->no, calc->keepDist);
+ }
+ else {
+ /* Adjusting the vertex weight,
+ * so that after interpolating it keeps a certain distance from the nearest position */
+ const float dist = sasqrt(nearest->dist_sq);
+ if (dist > FLT_EPSILON) {
+ /* linear interpolation */
+ interp_v3_v3v3(tmp_co, tmp_co, nearest->co, (dist - calc->keepDist) / dist);
+ }
+ else {
+ copy_v3_v3(tmp_co, nearest->co);
+ }
+ }
+ /* Convert the coordinates back to mesh coordinates */
+ BLI_space_transform_invert(&calc->local2target, tmp_co);
+ interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
+ }
+}
+
+static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
+{
BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
BVHTreeNearest nearest = NULL_BVHTreeNearest;
@@ -446,67 +553,11 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
nearest.index = -1;
nearest.dist_sq = FLT_MAX;
-
/* Find the nearest vertex */
-#ifndef __APPLE__
-#pragma omp parallel for default(none) private(i) firstprivate(nearest) shared(calc, treeData) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT)
-#endif
- for (i = 0; i < calc->numVerts; ++i) {
- float *co = calc->vertexCos[i];
- float tmp_co[3];
- float weight = defvert_array_find_weight_safe(calc->dvert, i, calc->vgroup);
-
- if (calc->invert_vgroup) {
- weight = 1.0f - weight;
- }
-
- if (weight == 0.0f) continue;
-
- /* Convert the vertex to tree coordinates */
- if (calc->vert) {
- copy_v3_v3(tmp_co, calc->vert[i].co);
- }
- else {
- copy_v3_v3(tmp_co, co);
- }
- BLI_space_transform_apply(&calc->local2target, tmp_co);
-
- /* Use local proximity heuristics (to reduce the nearest search)
- *
- * If we already had an hit before.. we assume this vertex is going to have a close hit to that other vertex
- * so we can initiate the "nearest.dist" with the expected value to that last hit.
- * This will lead in pruning of the search tree. */
- if (nearest.index != -1)
- nearest.dist_sq = len_squared_v3v3(tmp_co, nearest.co);
- else
- nearest.dist_sq = FLT_MAX;
-
- BLI_bvhtree_find_nearest(treeData.tree, tmp_co, &nearest, treeData.nearest_callback, &treeData);
-
- /* Found the nearest vertex */
- if (nearest.index != -1) {
- if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE) {
- /* Make the vertex stay on the front side of the face */
- madd_v3_v3v3fl(tmp_co, nearest.co, nearest.no, calc->keepDist);
- }
- else {
- /* Adjusting the vertex weight,
- * so that after interpolating it keeps a certain distance from the nearest position */
- const float dist = sasqrt(nearest.dist_sq);
- if (dist > FLT_EPSILON) {
- /* linear interpolation */
- interp_v3_v3v3(tmp_co, tmp_co, nearest.co, (dist - calc->keepDist) / dist);
- }
- else {
- copy_v3_v3(tmp_co, nearest.co);
- }
- }
-
- /* Convert the coordinates back to mesh coordinates */
- BLI_space_transform_invert(&calc->local2target, tmp_co);
- interp_v3_v3v3(co, co, tmp_co, weight); /* linear interpolation */
- }
- }
+ ShrinkwrapCalcCBData data = {.calc = calc, .treeData = &treeData};
+ BLI_task_parallel_range_ex(
+ 0, calc->numVerts, &data, &nearest, sizeof(nearest), shrinkwrap_calc_nearest_surface_point_cb_ex,
+ calc->numVerts > BKE_MESH_OMP_LIMIT, false);
free_bvhtree_from_mesh(&treeData);
}
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 5b6adb3778a..b0d19320230 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -2995,6 +2995,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) {
matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index;
+ matconv[a].datatypes[numdata].info_index = matconv[a].attribs.orco.gl_info_index;
matconv[a].datatypes[numdata].size = 3;
matconv[a].datatypes[numdata].type = GL_FLOAT;
numdata++;
@@ -3002,6 +3003,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
for (b = 0; b < matconv[a].attribs.tottface; b++) {
if (matconv[a].attribs.tface[b].array) {
matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index;
+ matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tface[b].gl_info_index;
matconv[a].datatypes[numdata].size = 2;
matconv[a].datatypes[numdata].type = GL_FLOAT;
numdata++;
@@ -3010,6 +3012,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
for (b = 0; b < matconv[a].attribs.totmcol; b++) {
if (matconv[a].attribs.mcol[b].array) {
matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index;
+ matconv[a].datatypes[numdata].info_index = matconv[a].attribs.mcol[b].gl_info_index;
matconv[a].datatypes[numdata].size = 4;
matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE;
numdata++;
@@ -3018,6 +3021,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm,
for (b = 0; b < matconv[a].attribs.tottang; b++) {
if (matconv[a].attribs.tottang && matconv[a].attribs.tang[b].array) {
matconv[a].datatypes[numdata].index = matconv[a].attribs.tang[b].gl_index;
+ matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tang[b].gl_info_index;
matconv[a].datatypes[numdata].size = 4;
matconv[a].datatypes[numdata].type = GL_FLOAT;
numdata++;
diff --git a/source/blender/blenlib/BLI_array_store.h b/source/blender/blenlib/BLI_array_store.h
new file mode 100644
index 00000000000..f4cbc07bf26
--- /dev/null
+++ b/source/blender/blenlib/BLI_array_store.h
@@ -0,0 +1,66 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_ARRAY_STORE_H__
+#define __BLI_ARRAY_STORE_H__
+
+/** \file BLI_array_store.h
+ * \ingroup bli
+ * \brief Efficient in-memory storage of multiple similar arrays.
+ */
+
+typedef struct BArrayStore BArrayStore;
+typedef struct BArrayState BArrayState;
+
+BArrayStore *BLI_array_store_create(
+ unsigned int stride, unsigned int chunk_count);
+void BLI_array_store_destroy(
+ BArrayStore *bs);
+void BLI_array_store_clear(
+ BArrayStore *bs);
+
+/* find the memory used by all states (expanded & real) */
+size_t BLI_array_store_calc_size_expanded_get(
+ const BArrayStore *bs);
+size_t BLI_array_store_calc_size_compacted_get(
+ const BArrayStore *bs);
+
+BArrayState *BLI_array_store_state_add(
+ BArrayStore *bs,
+ const void *data, const size_t data_len,
+ const BArrayState *state_reference);
+void BLI_array_store_state_remove(
+ BArrayStore *bs,
+ BArrayState *state);
+
+size_t BLI_array_store_state_size_get(
+ BArrayState *state);
+void BLI_array_store_state_data_get(
+ BArrayState *state,
+ void *data);
+void *BLI_array_store_state_data_get_alloc(
+ BArrayState *state,
+ size_t *r_data_len);
+
+/* only for tests */
+bool BLI_array_store_is_valid(
+ BArrayStore *bs);
+
+#endif /* __BLI_ARRAY_STORE_H__ */
diff --git a/source/blender/blenlib/BLI_stackdefines.h b/source/blender/blenlib/BLI_stackdefines.h
index b26dc3e26aa..42b11eb9a2b 100644
--- a/source/blender/blenlib/BLI_stackdefines.h
+++ b/source/blender/blenlib/BLI_stackdefines.h
@@ -31,28 +31,28 @@
/* only validate array-bounds in debug mode */
#ifdef DEBUG
# define STACK_DECLARE(stack) unsigned int _##stack##_index, _##stack##_totalloc
-# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)((_##stack##_totalloc) = tot))
-# define _STACK_SIZETEST(stack, off) (BLI_assert((_##stack##_index) + off <= _##stack##_totalloc))
+# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)((_##stack##_totalloc) = (tot)))
+# define _STACK_SIZETEST(stack, off) (BLI_assert((_##stack##_index) + (off) <= _##stack##_totalloc))
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) SWAP(unsigned int, _##stack_a##_totalloc, _##stack_b##_totalloc)
#else
# define STACK_DECLARE(stack) unsigned int _##stack##_index
-# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? tot : 0))
+# define STACK_INIT(stack, tot) ((void)stack, (void)((_##stack##_index) = 0), (void)(0 ? (tot) : 0))
# define _STACK_SIZETEST(stack, off) (void)(stack), (void)(off)
# define _STACK_SWAP_TOTALLOC(stack_a, stack_b) (void)(stack_a), (void)(stack_b)
#endif
-#define _STACK_BOUNDSTEST(stack, index) ((void)stack, BLI_assert((unsigned int)index < _##stack##_index))
+#define _STACK_BOUNDSTEST(stack, index) ((void)stack, BLI_assert((unsigned int)(index) < _##stack##_index))
#define STACK_SIZE(stack) ((void)stack, (_##stack##_index))
#define STACK_CLEAR(stack) {(void)stack; _##stack##_index = 0; } ((void)0)
/** add item to stack */
-#define STACK_PUSH(stack, val) ((void)stack, _STACK_SIZETEST(stack, 1), ((stack)[(_##stack##_index)++] = val))
+#define STACK_PUSH(stack, val) ((void)stack, _STACK_SIZETEST(stack, 1), ((stack)[(_##stack##_index)++] = (val)))
#define STACK_PUSH_RET(stack) ((void)stack, _STACK_SIZETEST(stack, 1), ((stack)[(_##stack##_index)++]))
#define STACK_PUSH_RET_PTR(stack) ((void)stack, _STACK_SIZETEST(stack, 1), &((stack)[(_##stack##_index)++]))
/** take last item from stack */
#define STACK_POP(stack) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : NULL)
#define STACK_POP_PTR(stack) ((_##stack##_index) ? &((stack)[--(_##stack##_index)]) : NULL)
-#define STACK_POP_DEFAULT(stack, r) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : r)
+#define STACK_POP_DEFAULT(stack, r) ((_##stack##_index) ? ((stack)[--(_##stack##_index)]) : (r))
/** look at last item (assumes non-empty stack) */
#define STACK_PEEK(stack) (BLI_assert(_##stack##_index), ((stack)[_##stack##_index - 1]))
#define STACK_PEEK_PTR(stack) (BLI_assert(_##stack##_index), &((stack)[_##stack##_index - 1]))
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 944ba60eb58..42d958774d8 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -52,6 +52,7 @@ set(SRC
intern/BLI_memarena.c
intern/BLI_mempool.c
intern/DLRB_tree.c
+ intern/array_store.c
intern/array_utils.c
intern/astar.c
intern/boxpack2d.c
@@ -120,6 +121,7 @@ set(SRC
BLI_alloca.h
BLI_args.h
BLI_array.h
+ BLI_array_store.h
BLI_array_utils.h
BLI_astar.h
BLI_bitmap.h
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 06946e520a8..0b5adab3929 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -441,7 +441,7 @@ static GHash *ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
gh->flag = flag;
ghash_buckets_reset(gh, nentries_reserve);
- gh->entrypool = BLI_mempool_create(GHASH_ENTRY_SIZE(flag & GHASH_FLAG_IS_GSET), 64, 64, BLI_MEMPOOL_NOP);
+ gh->entrypool = BLI_mempool_create(GHASH_ENTRY_SIZE(flag & GHASH_FLAG_IS_GSET), 0, 64, BLI_MEMPOOL_NOP);
return gh;
}
@@ -1287,7 +1287,7 @@ bool BLI_ghashutil_paircmp(const void *a, const void *b)
const GHashPair *A = a;
const GHashPair *B = b;
- return (BLI_ghashutil_ptrcmp(A->first, B->first) ||
+ return (BLI_ghashutil_ptrcmp(A->first, B->first) &&
BLI_ghashutil_ptrcmp(A->second, B->second));
}
diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c
index 7338804c685..38d15750761 100644
--- a/source/blender/blenlib/intern/BLI_mempool.c
+++ b/source/blender/blenlib/intern/BLI_mempool.c
@@ -57,12 +57,29 @@
#ifdef __BIG_ENDIAN__
/* Big Endian */
# define MAKE_ID(a, b, c, d) ( (int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d) )
+# define MAKE_ID_8(a, b, c, d, e, f, g, h) \
+ ((int64_t)(a) << 56 | (int64_t)(b) << 48 | (int64_t)(c) << 40 | (int64_t)(d) << 32 | \
+ (int64_t)(e) << 24 | (int64_t)(f) << 16 | (int64_t)(g) << 8 | (h) )
#else
/* Little Endian */
# define MAKE_ID(a, b, c, d) ( (int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a) )
+# define MAKE_ID_8(a, b, c, d, e, f, g, h) \
+ ((int64_t)(h) << 56 | (int64_t)(g) << 48 | (int64_t)(f) << 40 | (int64_t)(e) << 32 | \
+ (int64_t)(d) << 24 | (int64_t)(c) << 16 | (int64_t)(b) << 8 | (a) )
#endif
-#define FREEWORD MAKE_ID('f', 'r', 'e', 'e')
+/**
+ * Important that this value is an is _not_ aligned with ``sizeof(void *)``.
+ * So having a pointer to 2/4/8... aligned memory is enough to ensure the freeword will never be used.
+ * To be safe, use a word thats the same in both directions.
+ */
+#define FREEWORD ((sizeof(void *) > sizeof(int32_t)) ? \
+ MAKE_ID_8('e', 'e', 'r', 'f', 'f', 'r', 'e', 'e') : \
+ MAKE_ID('e', 'f', 'f', 'e'))
+
+/**
+ * The 'used' word just needs to be set to something besides FREEWORD.
+ */
#define USEDWORD MAKE_ID('u', 's', 'e', 'd')
/* currently totalloc isnt used */
@@ -87,7 +104,7 @@ static bool mempool_debug_memset = false;
*/
typedef struct BLI_freenode {
struct BLI_freenode *next;
- int freeword; /* used to identify this as a freed node */
+ intptr_t freeword; /* used to identify this as a freed node */
} BLI_freenode;
/**
diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c
new file mode 100644
index 00000000000..7f657f4a048
--- /dev/null
+++ b/source/blender/blenlib/intern/array_store.c
@@ -0,0 +1,1731 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenlib/intern/array_store.c
+ * \ingroup bli
+ * \brief Array storage to minimize duplication.
+ *
+ * This is done by splitting arrays into chunks and using copy-on-write (COW),
+ * to de-duplicate chunks,
+ * from the users perspective this is an implementation detail.
+ *
+ *
+ * Overview
+ * ========
+ *
+ *
+ * Data Structure
+ * --------------
+ *
+ * This diagram is an overview of the structure of a single array-store.
+ *
+ * \note The only 2 structues here which are referenced externally are the.
+ *
+ * - BArrayStore: The whole array store.
+ * - BArrayState: Represents a single state (array) of data.
+ * These can be add using a reference state, while this could be considered the previous or parent state.
+ * no relationship is kept, so the caller is free to add any state from the same BArrayStore as a reference.
+ *
+ * <pre>
+ * <+> BArrayStore: root data-structure,
+ * | can store many 'states', which share memory.
+ * |
+ * | This can store many arrays, however they must share the same 'stride'.
+ * | Arrays of different types will need to use a new BArrayStore.
+ * |
+ * +- <+> states (Collection of BArrayState's):
+ * | | Each represents an array added by the user of this API.
+ * | | and references a chunk_list (each state is a chunk_list user).
+ * | | Note that the list order has no significance.
+ * | |
+ * | +- <+> chunk_list (BChunkList):
+ * | | The chunks that make up this state.
+ * | | Each state is a chunk_list user,
+ * | | avoids duplicating lists when there is no change between states.
+ * | |
+ * | +- chunk_refs (List of BChunkRef): Each chunk_ref links to a a BChunk.
+ * | Each reference is a chunk user,
+ * | avoids duplicating smaller chunks of memory found in multiple states.
+ * |
+ * +- info (BArrayInfo):
+ * | Sizes and offsets for this array-store.
+ * | Also caches some variables for reuse.
+ * |
+ * +- <+> memory (BArrayMemory):
+ * | Memory pools for storing BArrayStore data.
+ * |
+ * +- chunk_list (Pool of BChunkList):
+ * | All chunk_lists, (reference counted, used by BArrayState).
+ * |
+ * +- chunk_ref (Pool of BChunkRef):
+ * | All chunk_refs (link between BChunkList & BChunk).
+ * |
+ * +- chunks (Pool of BChunk):
+ * All chunks, (reference counted, used by BChunkList).
+ * These have their headers hashed for reuse so we can quickly check for duplicates.
+ * </pre>
+ *
+ *
+ * De-Duplication
+ * --------------
+ *
+ * When creating a new state, a previous state can be given as a reference,
+ * matching chunks from this state are re-used in the new state.
+ *
+ * First matches at either end of the array are detected.
+ * For identical arrays this is all thats needed.
+ *
+ * De-duplication is performed on any remaining chunks, by hasing the first few bytes of the chunk
+ * (see: BCHUNK_HASH_TABLE_ACCUMULATE_STEPS).
+ *
+ * \note This is cached for reuse since the referenced data never changes.
+ *
+ * An array is created to store hash values at every 'stride',
+ * then stepped over to search for matching chunks.
+ *
+ * Once a match is found, there is a high chance next chunks match too,
+ * so this is checked to avoid performing so many hash-lookups.
+ * Otherwise new chunks are created.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_mempool.h"
+
+#include "BLI_strict_flags.h"
+
+#include "BLI_array_store.h" /* own include */
+
+/* only for BLI_array_store_is_valid */
+#include "BLI_ghash.h"
+
+/** \name Defines
+ *
+ * Some of the logic for merging is quite involved,
+ * support disabling some parts of this.
+ * \{ */
+
+/* Scan first chunks (happy path when beginning of the array matches).
+ * When the array is a perfect match, we can re-use the entire list.
+ *
+ * Note that disabling makes some tests fail that check for output-size.
+ */
+#define USE_FASTPATH_CHUNKS_FIRST
+
+/* Scan last chunks (happy path when end of the array matches).
+ * When the end of the array matches, we can quickly add these chunks.
+ * note that we will add contiguous matching chunks
+ * so this isn't as useful as USE_FASTPATH_CHUNKS_FIRST,
+ * however it avoids adding matching chunks into the lookup table,
+ * so creating the lookup table won't be as expensive.
+ */
+#ifdef USE_FASTPATH_CHUNKS_FIRST
+# define USE_FASTPATH_CHUNKS_LAST
+#endif
+
+/* For arrays of matching length, test that *enough* of the chunks are aligned,
+ * and simply step over both arrays, using matching chunks.
+ * This avoids overhead of using a lookup table for cases when we can assume they're mostly aligned.
+ */
+#define USE_ALIGN_CHUNKS_TEST
+
+/* Accumulate hashes from right to left so we can create a hash for the chunk-start.
+ * This serves to increase uniqueness and will help when there is many values which are the same.
+ */
+#define USE_HASH_TABLE_ACCUMULATE
+
+#ifdef USE_HASH_TABLE_ACCUMULATE
+/* Number of times to propagate hashes back.
+ * Effectively a 'triangle-number'.
+ * so 4 -> 7, 5 -> 10, 6 -> 15... etc.
+ */
+# define BCHUNK_HASH_TABLE_ACCUMULATE_STEPS 4
+#else
+/* How many items to hash (multiplied by stride)
+ */
+# define BCHUNK_HASH_LEN 4
+#endif
+
+/* Calculate the key once and reuse it
+ */
+#define USE_HASH_TABLE_KEY_CACHE
+#ifdef USE_HASH_TABLE_KEY_CACHE
+# define HASH_TABLE_KEY_UNSET ((uint64_t)-1)
+# define HASH_TABLE_KEY_FALLBACK ((uint64_t)-2)
+#endif
+
+/* How much larger the table is then the total number of chunks.
+ */
+#define BCHUNK_HASH_TABLE_MUL 3
+
+/* Merge too small/large chunks:
+ *
+ * Using this means chunks below a threshold will be merged together.
+ * Even though short term this uses more memory,
+ * long term the overhead of maintaining many small chunks is reduced.
+ * This is defined by setting the minimum chunk size (as a fraction of the regular chunk size).
+ *
+ * Chunks may also become too large (when incrementally growing an array),
+ * this also enables chunk splitting.
+ */
+#define USE_MERGE_CHUNKS
+
+#ifdef USE_MERGE_CHUNKS
+/* Merge chunks smaller then: (chunk_size / BCHUNK_MIN_SIZE_DIV)
+ */
+# define BCHUNK_SIZE_MIN_DIV 8
+
+/* Disallow chunks bigger then the regular chunk size scaled by this value
+ * note: must be at least 2!
+ * however, this code runs wont run in tests unless its ~1.1 ugh.
+ * so lower only to check splitting works.
+ */
+# define BCHUNK_SIZE_MAX_MUL 2
+#endif /* USE_MERGE_CHUNKS */
+
+/* slow (keep disabled), but handy for debugging */
+// #define USE_VALIDATE_LIST_SIZE
+
+// #define USE_VALIDATE_LIST_DATA_PARTIAL
+
+// #define USE_PARANOID_CHECKS
+
+/** \} */
+
+
+/** \name Internal Structs
+ * \{ */
+
+typedef unsigned int uint;
+typedef unsigned char ubyte;
+
+typedef uint64_t hash_key;
+
+
+typedef struct BArrayInfo {
+ size_t chunk_stride;
+ uint chunk_count;
+
+ /* pre-calculated */
+ size_t chunk_byte_size;
+ size_t chunk_byte_size_min;
+
+ size_t accum_read_ahead_bytes;
+#ifdef USE_HASH_TABLE_ACCUMULATE
+ size_t accum_steps;
+ size_t accum_read_ahead_len;
+#endif
+} BArrayInfo;
+
+typedef struct BArrayMemory {
+ BLI_mempool *chunk_list; /* BChunkList */
+ BLI_mempool *chunk_ref; /* BChunkRef */
+ BLI_mempool *chunk; /* BChunk */
+} BArrayMemory;
+
+/**
+ * Main storage for all states
+ */
+typedef struct BArrayStore {
+ /* static */
+ BArrayInfo info;
+
+ /* memory storage */
+ BArrayMemory memory;
+
+ /**
+ * #BArrayState may be in any order (logic should never depend on state order).
+ */
+ ListBase states;
+} BArrayStore;
+
+/**
+ * A single instance of an array.
+ *
+ * This is how external API's hold a reference to an in-memory state,
+ * although the struct is private.
+ *
+ * \note Currently each 'state' is allocated separately.
+ * While this could be moved to a memory pool,
+ * it makes it easier to trace invalid usage, so leave as-is for now.
+ */
+typedef struct BArrayState {
+ /** linked list in #BArrayStore.states */
+ struct BArrayState *next, *prev;
+
+ struct BChunkList *chunk_list; /* BChunkList's */
+
+} BArrayState;
+
+typedef struct BChunkList {
+ ListBase chunk_refs; /* BChunkRef's */
+ uint chunk_refs_len; /* BLI_listbase_count(chunks), store for reuse. */
+ size_t total_size; /* size of all chunks */
+
+ /** number of #BArrayState using this. */
+ int users;
+} BChunkList;
+
+/* a chunk of an array */
+typedef struct BChunk {
+ const ubyte *data;
+ size_t data_len;
+ /** number of #BChunkList using this. */
+ int users;
+
+#ifdef USE_HASH_TABLE_KEY_CACHE
+ hash_key key;
+#endif
+} BChunk;
+
+/**
+ * Links to store #BChunk data in #BChunkList.chunks.
+ */
+typedef struct BChunkRef {
+ struct BChunkRef *next, *prev;
+ BChunk *link;
+} BChunkRef;
+
+/**
+ * Single linked list used when putting chunks into a temporary table,
+ * used for lookups.
+ *
+ * Point to the #BChunkRef, not the #BChunk,
+ * to allow talking down the chunks in-order until a mis-match is found,
+ * this avoids having to do so many table lookups.
+ */
+typedef struct BTableRef {
+ struct BTableRef *next;
+ const BChunkRef *cref;
+} BTableRef;
+
+/** \} */
+
+
+static size_t bchunk_list_size(const BChunkList *chunk_list);
+
+
+/** \name Internal BChunk API
+ * \{ */
+
+static BChunk *bchunk_new(
+ BArrayMemory *bs_mem, const ubyte *data, const size_t data_len)
+{
+ BChunk *chunk = BLI_mempool_alloc(bs_mem->chunk);
+ chunk->data = data;
+ chunk->data_len = data_len;
+ chunk->users = 0;
+#ifdef USE_HASH_TABLE_KEY_CACHE
+ chunk->key = HASH_TABLE_KEY_UNSET;
+#endif
+ return chunk;
+}
+
+static BChunk *bchunk_new_copydata(
+ BArrayMemory *bs_mem, const ubyte *data, const size_t data_len)
+{
+ ubyte *data_copy = MEM_mallocN(data_len, __func__);
+ memcpy(data_copy, data, data_len);
+ return bchunk_new(bs_mem, data_copy, data_len);
+}
+
+static void bchunk_decref(
+ BArrayMemory *bs_mem, BChunk *chunk)
+{
+ BLI_assert(chunk->users > 0);
+ if (chunk->users == 1) {
+ MEM_freeN((void *)chunk->data);
+ BLI_mempool_free(bs_mem->chunk, chunk);
+ }
+ else {
+ chunk->users -= 1;
+ }
+}
+
+static bool bchunk_data_compare(
+ const BChunk *chunk,
+ const ubyte *data_base, const size_t data_base_len,
+ const size_t offset)
+{
+ if (offset + (size_t)chunk->data_len <= data_base_len) {
+ return (memcmp(&data_base[offset], chunk->data, chunk->data_len) == 0);
+ }
+ else {
+ return false;
+ }
+}
+
+/** \} */
+
+
+/** \name Internal BChunkList API
+ * \{ */
+
+static BChunkList *bchunk_list_new(
+ BArrayMemory *bs_mem, size_t total_size)
+{
+ BChunkList *chunk_list = BLI_mempool_alloc(bs_mem->chunk_list);
+
+ BLI_listbase_clear(&chunk_list->chunk_refs);
+ chunk_list->chunk_refs_len = 0;
+ chunk_list->total_size = total_size;
+ chunk_list->users = 0;
+ return chunk_list;
+}
+
+static void bchunk_list_decref(
+ BArrayMemory *bs_mem, BChunkList *chunk_list)
+{
+ BLI_assert(chunk_list->users > 0);
+ if (chunk_list->users == 1) {
+ for (BChunkRef *cref = chunk_list->chunk_refs.first, *cref_next; cref; cref = cref_next) {
+ cref_next = cref->next;
+ bchunk_decref(bs_mem, cref->link);
+ BLI_mempool_free(bs_mem->chunk_ref, cref);
+ }
+
+ BLI_mempool_free(bs_mem->chunk_list, chunk_list);
+ }
+ else {
+ chunk_list->users -= 1;
+ }
+}
+
+#ifdef USE_VALIDATE_LIST_SIZE
+# ifndef NDEBUG
+# define ASSERT_CHUNKLIST_SIZE(chunk_list, n) BLI_assert(bchunk_list_size(chunk_list) == n)
+# endif
+#endif
+#ifndef ASSERT_CHUNKLIST_SIZE
+# define ASSERT_CHUNKLIST_SIZE(chunk_list, n) (EXPR_NOP(chunk_list), EXPR_NOP(n))
+#endif
+
+
+#ifdef USE_VALIDATE_LIST_DATA_PARTIAL
+static size_t bchunk_list_data_check(
+ const BChunkList *chunk_list, const ubyte *data)
+{
+ size_t total_size = 0;
+ for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) {
+ if (memcmp(&data[total_size], cref->link->data, cref->link->data_len) != 0) {
+ return false;
+ }
+ total_size += cref->link->data_len;
+ }
+ return true;
+}
+# define ASSERT_CHUNKLIST_DATA(chunk_list, data) BLI_assert(bchunk_list_data_check(chunk_list, data))
+#else
+# define ASSERT_CHUNKLIST_DATA(chunk_list, data) (EXPR_NOP(chunk_list), EXPR_NOP(data))
+#endif
+
+
+#ifdef USE_MERGE_CHUNKS
+static void bchunk_list_ensure_min_size_last(
+ const BArrayInfo *info, BArrayMemory *bs_mem,
+ BChunkList *chunk_list)
+{
+ BChunkRef *cref = chunk_list->chunk_refs.last;
+ if (cref && cref->prev) {
+ /* both are decref'd after use (end of this block) */
+ BChunk *chunk_curr = cref->link;
+ BChunk *chunk_prev = cref->prev->link;
+
+ if (MIN2(chunk_prev->data_len, chunk_curr->data_len) < info->chunk_byte_size_min) {
+ const size_t data_merge_len = chunk_prev->data_len + chunk_curr->data_len;
+ /* we could pass, but no need */
+ if (data_merge_len <= (info->chunk_byte_size * BCHUNK_SIZE_MAX_MUL)) {
+ /* we have enough space to merge */
+
+ /* remove last from linklist */
+ BLI_assert(chunk_list->chunk_refs.last != chunk_list->chunk_refs.first);
+ cref->prev->next = NULL;
+ chunk_list->chunk_refs.last = cref->prev;
+ chunk_list->chunk_refs_len -= 1;
+
+ ubyte *data_merge = MEM_mallocN(data_merge_len, __func__);
+ memcpy(data_merge, chunk_prev->data, chunk_prev->data_len);
+ memcpy(&data_merge[chunk_prev->data_len], chunk_curr->data, chunk_curr->data_len);
+
+ cref->prev->link = bchunk_new(bs_mem, data_merge, data_merge_len);
+ cref->prev->link->users += 1;
+
+ BLI_mempool_free(bs_mem->chunk_ref, cref);
+ }
+ else {
+ /* If we always merge small slices, we should _almost_ never end up having very large chunks.
+ * Gradual expanding on contracting will cause this.
+ *
+ * if we do, the code below works (test by setting 'BCHUNK_SIZE_MAX_MUL = 1.2') */
+
+ /* keep chunk on the left hand side a regular size */
+ const size_t split = info->chunk_byte_size;
+
+ /* merge and split */
+ const size_t data_prev_len = split;
+ const size_t data_curr_len = data_merge_len - split;
+ ubyte *data_prev = MEM_mallocN(data_prev_len, __func__);
+ ubyte *data_curr = MEM_mallocN(data_curr_len, __func__);
+
+ if (data_prev_len <= chunk_prev->data_len) {
+ const size_t data_curr_shrink_len = chunk_prev->data_len - data_prev_len;
+
+ /* setup 'data_prev' */
+ memcpy(data_prev, chunk_prev->data, data_prev_len);
+
+ /* setup 'data_curr' */
+ memcpy(data_curr, &chunk_prev->data[data_prev_len], data_curr_shrink_len);
+ memcpy(&data_curr[data_curr_shrink_len], chunk_curr->data, chunk_curr->data_len);
+ }
+ else {
+ BLI_assert(data_curr_len <= chunk_curr->data_len);
+ BLI_assert(data_prev_len >= chunk_prev->data_len);
+
+ const size_t data_prev_grow_len = data_prev_len - chunk_prev->data_len;
+
+ /* setup 'data_prev' */
+ memcpy(data_prev, chunk_prev->data, chunk_prev->data_len);
+ memcpy(&data_prev[chunk_prev->data_len], chunk_curr->data, data_prev_grow_len);
+
+ /* setup 'data_curr' */
+ memcpy(data_curr, &chunk_curr->data[data_prev_grow_len], data_curr_len);
+ }
+
+ cref->prev->link = bchunk_new(bs_mem, data_prev, data_prev_len);
+ cref->prev->link->users += 1;
+
+ cref->link = bchunk_new(bs_mem, data_curr, data_curr_len);
+ cref->link->users += 1;
+ }
+
+ /* free zero users */
+ bchunk_decref(bs_mem, chunk_curr);
+ bchunk_decref(bs_mem, chunk_prev);
+ }
+ }
+}
+#endif /* USE_MERGE_CHUNKS */
+
+/**
+ * Append and don't manage merging small chunks.
+ */
+static bool bchunk_list_append_only(
+ BArrayMemory *bs_mem,
+ BChunkList *chunk_list, BChunk *chunk)
+{
+ BChunkRef *cref = BLI_mempool_alloc(bs_mem->chunk_ref);
+ BLI_addtail(&chunk_list->chunk_refs, cref);
+ cref->link = chunk;
+ chunk_list->chunk_refs_len += 1;
+ chunk->users += 1;
+ return chunk;
+}
+
+static void bchunk_list_append_data(
+ const BArrayInfo *info, BArrayMemory *bs_mem,
+ BChunkList *chunk_list,
+ const ubyte *data, const size_t data_len)
+{
+ BLI_assert(data_len != 0);
+ // printf("data_len: %d\n", data_len);
+#ifdef USE_MERGE_CHUNKS
+ if (!BLI_listbase_is_empty(&chunk_list->chunk_refs)) {
+ BChunkRef *cref = chunk_list->chunk_refs.last;
+ BChunk *chunk_prev = cref->link;
+
+ if (MIN2(chunk_prev->data_len, data_len) < info->chunk_byte_size_min) {
+ const size_t data_merge_len = chunk_prev->data_len + data_len;
+ /* realloc for single user */
+ if (cref->link->users == 1) {
+ ubyte *data_merge = MEM_reallocN((void *)cref->link->data, data_merge_len);
+ memcpy(&data_merge[chunk_prev->data_len], data, data_len);
+ cref->link->data = data_merge;
+ cref->link->data_len = data_merge_len;
+ }
+ else {
+ ubyte *data_merge = MEM_mallocN(data_merge_len, __func__);
+ memcpy(data_merge, chunk_prev->data, chunk_prev->data_len);
+ memcpy(&data_merge[chunk_prev->data_len], data, data_len);
+ cref->link = bchunk_new(bs_mem, data_merge, data_merge_len);
+ cref->link->users += 1;
+ bchunk_decref(bs_mem, chunk_prev);
+ }
+ return;
+ }
+ }
+#else
+ UNUSED_VARS(info);
+#endif /* USE_MERGE_CHUNKS */
+
+ BChunk *chunk = bchunk_new_copydata(bs_mem, data, data_len);
+ bchunk_list_append_only(bs_mem, chunk_list, chunk);
+
+ /* don't run this, instead preemptively avoid creating a chunk only to merge it (above). */
+#if 0
+#ifdef USE_MERGE_CHUNKS
+ bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list, chunk_size_min);
+#endif
+#endif
+}
+
+static void bchunk_list_append(
+ const BArrayInfo *info, BArrayMemory *bs_mem,
+ BChunkList *chunk_list,
+ BChunk *chunk)
+{
+ bchunk_list_append_only(bs_mem, chunk_list, chunk);
+
+#ifdef USE_MERGE_CHUNKS
+ bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list);
+#else
+ UNUSED_VARS(info);
+#endif
+}
+
+static void bchunk_list_fill_from_array(
+ const BArrayInfo *info, BArrayMemory *bs_mem,
+ BChunkList *chunk_list,
+ const ubyte *data,
+ const size_t data_len)
+{
+ BLI_assert(BLI_listbase_is_empty(&chunk_list->chunk_refs));
+
+ size_t data_last_chunk_len = 0;
+ size_t data_trim_len = data_len;
+
+#ifdef USE_MERGE_CHUNKS
+ /* avoid creating too-small chunks
+ * more efficient then merging after */
+ if (data_len > info->chunk_byte_size) {
+ data_last_chunk_len = (data_trim_len % info->chunk_byte_size);
+ data_trim_len = data_trim_len - data_last_chunk_len;
+ if (data_last_chunk_len) {
+ if (data_last_chunk_len < info->chunk_byte_size_min) {
+ /* may be zero and thats OK */
+ data_trim_len -= info->chunk_byte_size;
+ data_last_chunk_len += info->chunk_byte_size;
+ }
+ }
+ }
+ else {
+ data_trim_len = 0;
+ data_last_chunk_len = data_len;
+ }
+#else
+ data_last_chunk_len = (data_trim_len % info->chunk_byte_size);
+ data_trim_len = data_trim_len - data_last_chunk_len;
+#endif
+
+
+ BLI_assert(data_trim_len + data_last_chunk_len == data_len);
+
+ size_t i_prev = 0;
+ while (i_prev < data_trim_len) {
+ const size_t i = i_prev + info->chunk_byte_size;
+ BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], i - i_prev);
+ bchunk_list_append_only(bs_mem, chunk_list, chunk);
+ i_prev = i;
+ }
+
+ if (data_last_chunk_len) {
+ BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], data_last_chunk_len);
+ bchunk_list_append_only(bs_mem, chunk_list, chunk);
+ // i_prev = data_len;
+ }
+
+#ifdef USE_MERGE_CHUNKS
+ if (data_len > info->chunk_byte_size) {
+ BLI_assert(((BChunkRef *)chunk_list->chunk_refs.last)->link->data_len >= info->chunk_byte_size_min);
+ }
+#endif
+
+ /* works but better avoid redundant re-alloc */
+#if 0
+#ifdef USE_MERGE_CHUNKS
+ bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list);
+#endif
+#endif
+
+ ASSERT_CHUNKLIST_SIZE(chunk_list, data_len);
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+}
+
+
+/* ---------------------------------------------------------------------------
+ * Internal Table Lookup Functions
+ */
+
+/** \name Internal Hashing/De-Duplication API
+ *
+ * Only used by #bchunk_list_from_data_merge
+ * \{ */
+
+#define HASH_INIT (5381)
+
+BLI_INLINE uint hash_data_single(const ubyte p)
+{
+ return (HASH_INIT << 5) + HASH_INIT + (unsigned int)p;
+}
+
+/* hash bytes, from BLI_ghashutil_strhash_n */
+static uint hash_data(const ubyte *key, size_t n)
+{
+ const signed char *p;
+ unsigned int h = HASH_INIT;
+
+ for (p = (const signed char *)key; n--; p++) {
+ h = (h << 5) + h + (unsigned int)*p;
+ }
+
+ return h;
+}
+
+#undef HASH_INIT
+
+
+#ifdef USE_HASH_TABLE_ACCUMULATE
+static void hash_array_from_data(
+ const BArrayInfo *info, const ubyte *data_slice, const size_t data_slice_len,
+ hash_key *hash_array)
+{
+ if (info->chunk_stride != 1) {
+ for (size_t i = 0, i_step = 0; i_step < data_slice_len; i++, i_step += info->chunk_stride) {
+ hash_array[i] = hash_data(&data_slice[i_step], info->chunk_stride);
+ }
+ }
+ else {
+ /* fast-path for bytes */
+ for (size_t i = 0; i < data_slice_len; i++) {
+ hash_array[i] = hash_data_single(data_slice[i]);
+ }
+ }
+}
+
+/*
+ * Similar to hash_array_from_data,
+ * but able to step into the next chunk if we run-out of data.
+ */
+static void hash_array_from_cref(
+ const BArrayInfo *info, const BChunkRef *cref, const size_t data_len,
+ hash_key *hash_array)
+{
+ const size_t hash_array_len = data_len / info->chunk_stride;
+ size_t i = 0;
+ do {
+ size_t i_next = hash_array_len - i;
+ size_t data_trim_len = i_next * info->chunk_stride;
+ if (data_trim_len > cref->link->data_len) {
+ data_trim_len = cref->link->data_len;
+ i_next = data_trim_len / info->chunk_stride;
+ }
+ BLI_assert(data_trim_len <= cref->link->data_len);
+ hash_array_from_data(info, cref->link->data, data_trim_len, &hash_array[i]);
+ i += i_next;
+ cref = cref->next;
+ } while ((i < hash_array_len) && (cref != NULL));
+
+ /* If this isn't equal, the caller didn't properly check
+ * that there was enough data left in all chunks */
+ BLI_assert(i == hash_array_len);
+}
+
+static void hash_accum(hash_key *hash_array, const size_t hash_array_len, size_t iter_steps)
+{
+ /* _very_ unlikely, can happen if you select a chunk-size of 1 for example. */
+ if (UNLIKELY((iter_steps > hash_array_len))) {
+ iter_steps = hash_array_len;
+ }
+
+ const size_t hash_array_search_len = hash_array_len - iter_steps;
+ while (iter_steps != 0) {
+ const size_t hash_offset = iter_steps;
+ for (uint i = 0; i < hash_array_search_len; i++) {
+ hash_array[i] += (hash_array[i + hash_offset]) * ((hash_array[i] & 0xff) + 1);
+ }
+ iter_steps -= 1;
+ }
+}
+
+/**
+ * When we only need a single value, can use a small optimization.
+ * we can avoid accumulating the tail of the array a little, each iteration.
+ */
+static void hash_accum_single(hash_key *hash_array, const size_t hash_array_len, size_t iter_steps)
+{
+ BLI_assert(iter_steps <= hash_array_len);
+ if (UNLIKELY(!(iter_steps <= hash_array_len))) {
+ /* while this shouldn't happen, avoid crashing */
+ iter_steps = hash_array_len;
+ }
+ /* We can increase this value each step to avoid accumulating quite as much
+ * while getting the same results as hash_accum */
+ size_t iter_steps_sub = iter_steps;
+
+ while (iter_steps != 0) {
+ const size_t hash_array_search_len = hash_array_len - iter_steps_sub;
+ const size_t hash_offset = iter_steps;
+ for (uint i = 0; i < hash_array_search_len; i++) {
+ hash_array[i] += (hash_array[i + hash_offset]) * ((hash_array[i] & 0xff) + 1);
+ }
+ iter_steps -= 1;
+ iter_steps_sub += iter_steps;
+ }
+}
+
+static hash_key key_from_chunk_ref(
+ const BArrayInfo *info, const BChunkRef *cref,
+ /* avoid reallicating each time */
+ hash_key *hash_store, const size_t hash_store_len)
+{
+ /* in C, will fill in a reusable array */
+ BChunk *chunk = cref->link;
+ BLI_assert(info->accum_read_ahead_bytes * info->chunk_stride);
+
+ if (info->accum_read_ahead_bytes <= chunk->data_len) {
+ hash_key key;
+
+#ifdef USE_HASH_TABLE_KEY_CACHE
+ key = chunk->key;
+ if (key != HASH_TABLE_KEY_UNSET) {
+ /* Using key cache!
+ * avoids calculating every time */
+ }
+ else {
+ hash_array_from_cref(info, cref, info->accum_read_ahead_bytes, hash_store);
+ hash_accum_single(hash_store, hash_store_len, info->accum_steps);
+ key = hash_store[0];
+
+ /* cache the key */
+ if (key == HASH_TABLE_KEY_UNSET) {
+ key = HASH_TABLE_KEY_FALLBACK;
+ }
+ chunk->key = key;
+ }
+#else
+ hash_array_from_cref(info, cref, info->accum_read_ahead_bytes, hash_store);
+ hash_accum_single(hash_store, hash_store_len, info->accum_steps);
+ key = hash_store[0];
+#endif
+ return key;
+ }
+ else {
+ /* corner case - we're too small, calculate the key each time. */
+
+ hash_array_from_cref(info, cref, info->accum_read_ahead_bytes, hash_store);
+ hash_accum_single(hash_store, hash_store_len, info->accum_steps);
+ hash_key key = hash_store[0];
+
+#ifdef USE_HASH_TABLE_KEY_CACHE
+ if (UNLIKELY(key == HASH_TABLE_KEY_UNSET)) {
+ key = HASH_TABLE_KEY_FALLBACK;
+ }
+#endif
+ return key;
+ }
+}
+
+static const BChunkRef *table_lookup(
+ const BArrayInfo *info, BTableRef **table, const size_t table_len, const size_t i_table_start,
+ const ubyte *data, const size_t data_len, const size_t offset, const hash_key *table_hash_array)
+{
+ size_t size_left = data_len - offset;
+ hash_key key = table_hash_array[((offset - i_table_start) / info->chunk_stride)];
+ size_t key_index = (size_t)(key % (hash_key)table_len);
+ for (BTableRef *tref = table[key_index]; tref; tref = tref->next) {
+ const BChunkRef *cref = tref->cref;
+#ifdef USE_HASH_TABLE_KEY_CACHE
+ if (cref->link->key == key)
+#endif
+ {
+ BChunk *chunk_test = cref->link;
+ if (chunk_test->data_len <= size_left) {
+ if (bchunk_data_compare(chunk_test, data, data_len, offset)) {
+ /* we could remove the chunk from the table, to avoid multiple hits */
+ return cref;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+#else /* USE_HASH_TABLE_ACCUMULATE */
+
+/* NON USE_HASH_TABLE_ACCUMULATE code (simply hash each chunk) */
+
+static hash_key key_from_chunk_ref(const BArrayInfo *info, const BChunkRef *cref)
+{
+ const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride;
+ hash_key key;
+ BChunk *chunk = cref->link;
+
+#ifdef USE_HASH_TABLE_KEY_CACHE
+ key = chunk->key;
+ if (key != HASH_TABLE_KEY_UNSET) {
+ /* Using key cache!
+ * avoids calculating every time */
+ }
+ else {
+ /* cache the key */
+ key = hash_data(chunk->data, data_hash_len);
+ if (key == HASH_TABLE_KEY_UNSET) {
+ key = HASH_TABLE_KEY_FALLBACK;
+ }
+ chunk->key = key;
+ }
+#else
+ key = hash_data(chunk->data, data_hash_len);
+#endif
+
+ return key;
+}
+
+static const BChunkRef *table_lookup(
+ const BArrayInfo *info, BTableRef **table, const size_t table_len, const uint UNUSED(i_table_start),
+ const ubyte *data, const size_t data_len, const size_t offset, const hash_key *UNUSED(table_hash_array))
+{
+ const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; /* TODO, cache */
+
+ size_t size_left = data_len - offset;
+ hash_key key = hash_data(&data[offset], MIN2(data_hash_len, size_left));
+ size_t key_index = (size_t)(key % (hash_key)table_len);
+ for (BTableRef *tref = table[key_index]; tref; tref = tref->next) {
+ const BChunkRef *cref = tref->cref;
+#ifdef USE_HASH_TABLE_KEY_CACHE
+ if (cref->link->key == key)
+#endif
+ {
+ BChunk *chunk_test = cref->link;
+ if (chunk_test->data_len <= size_left) {
+ if (bchunk_data_compare(chunk_test, data, data_len, offset)) {
+ /* we could remove the chunk from the table, to avoid multiple hits */
+ return cref;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+#endif /* USE_HASH_TABLE_ACCUMULATE */
+
+/* End Table Lookup
+ * ---------------- */
+
+/** \} */
+
+/**
+ * \param data: Data to store in the returned value.
+ * \param data_len_original: Length of data in bytes.
+ * \param chunk_list_reference: Reuse this list or chunks within it, don't modify its content.
+ * \note Caller is responsible for adding the user.
+ */
+static BChunkList *bchunk_list_from_data_merge(
+ const BArrayInfo *info, BArrayMemory *bs_mem,
+ const ubyte *data, const size_t data_len_original,
+ const BChunkList *chunk_list_reference)
+{
+ ASSERT_CHUNKLIST_SIZE(chunk_list_reference, chunk_list_reference->total_size);
+
+ /* -----------------------------------------------------------------------
+ * Fast-Path for exact match
+ * Check for exact match, if so, return the current list.
+ */
+
+ const BChunkRef *cref_match_first = NULL;
+
+ uint chunk_list_reference_skip_len = 0;
+ size_t chunk_list_reference_skip_bytes = 0;
+ size_t i_prev = 0;
+
+#ifdef USE_FASTPATH_CHUNKS_FIRST
+ bool full_match = false;
+
+ {
+ full_match = true;
+
+ const BChunkRef *cref = chunk_list_reference->chunk_refs.first;
+ while (i_prev < data_len_original) {
+ if (cref != NULL && bchunk_data_compare(cref->link, data, data_len_original, i_prev)) {
+ cref_match_first = cref;
+ chunk_list_reference_skip_len += 1;
+ chunk_list_reference_skip_bytes += cref->link->data_len;
+ i_prev += cref->link->data_len;
+ cref = cref->next;
+ }
+ else {
+ full_match = false;
+ break;
+ }
+ }
+
+ if (full_match) {
+ if (chunk_list_reference->total_size == data_len_original) {
+ return (BChunkList *)chunk_list_reference;
+ }
+ }
+ }
+
+ /* End Fast-Path (first)
+ * --------------------- */
+
+#endif /* USE_FASTPATH_CHUNKS_FIRST */
+
+ /* Copy until we have a mismatch */
+ BChunkList *chunk_list = bchunk_list_new(bs_mem, data_len_original);
+ if (cref_match_first != NULL) {
+ size_t chunk_size_step = 0;
+ const BChunkRef *cref = chunk_list_reference->chunk_refs.first;
+ while (true) {
+ BChunk *chunk = cref->link;
+ chunk_size_step += chunk->data_len;
+ bchunk_list_append_only(bs_mem, chunk_list, chunk);
+ ASSERT_CHUNKLIST_SIZE(chunk_list, chunk_size_step);
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+ if (cref == cref_match_first) {
+ break;
+ }
+ else {
+ cref = cref->next;
+ }
+ }
+ /* happens when bytes are removed from the end of the array */
+ if (chunk_size_step == data_len_original) {
+ return chunk_list;
+ }
+
+ i_prev = chunk_size_step;
+ }
+ else {
+ i_prev = 0;
+ }
+
+ /* ------------------------------------------------------------------------
+ * Fast-Path for end chunks
+ *
+ * Check for trailing chunks
+ */
+
+ /* In this case use 'chunk_list_reference_last' to define the last index
+ * index_match_last = -1 */
+
+ /* warning, from now on don't use len(data)
+ * since we want to ignore chunks already matched */
+ size_t data_len = data_len_original;
+#define data_len_original invalid_usage
+#ifdef data_len_original /* quiet warning */
+#endif
+
+ const BChunkRef *chunk_list_reference_last = NULL;
+
+#ifdef USE_FASTPATH_CHUNKS_LAST
+ if (!BLI_listbase_is_empty(&chunk_list_reference->chunk_refs)) {
+ const BChunkRef *cref = chunk_list_reference->chunk_refs.last;
+ while ((cref->prev != NULL) &&
+ (cref != cref_match_first) &&
+ (cref->link->data_len <= data_len - i_prev))
+ {
+ BChunk *chunk_test = cref->link;
+ size_t offset = data_len - chunk_test->data_len;
+ if (bchunk_data_compare(chunk_test, data, data_len, offset)) {
+ data_len = offset;
+ chunk_list_reference_last = cref;
+ chunk_list_reference_skip_len += 1;
+ chunk_list_reference_skip_bytes += cref->link->data_len;
+ cref = cref->prev;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ /* End Fast-Path (last)
+ * -------------------- */
+#endif /* USE_FASTPATH_CHUNKS_LAST */
+
+ /* -----------------------------------------------------------------------
+ * Check for aligned chunks
+ *
+ * This saves a lot of searching, so use simple heuristics to detect aligned arrays.
+ * (may need to tweak exact method).
+ */
+
+ bool use_aligned = false;
+
+#ifdef USE_ALIGN_CHUNKS_TEST
+ if (chunk_list->total_size == chunk_list_reference->total_size) {
+ /* if we're already a quarter aligned */
+ if (data_len - i_prev <= chunk_list->total_size / 4) {
+ use_aligned = true;
+ }
+ else {
+ /* TODO, walk over chunks and check if some arbitrary amount align */
+ }
+ }
+#endif /* USE_ALIGN_CHUNKS_TEST */
+
+ /* End Aligned Chunk Case
+ * ----------------------- */
+
+ if (use_aligned) {
+ /* Copy matching chunks, creates using the same 'layout' as the reference */
+ const BChunkRef *cref = cref_match_first ? cref_match_first->next : chunk_list_reference->chunk_refs.first;
+ while (i_prev != data_len) {
+ const size_t i = i_prev + cref->link->data_len;
+ BLI_assert(i != i_prev);
+
+ if ((cref != chunk_list_reference_last) &&
+ bchunk_data_compare(cref->link, data, data_len, i_prev))
+ {
+ bchunk_list_append(info, bs_mem, chunk_list, cref->link);
+ ASSERT_CHUNKLIST_SIZE(chunk_list, i);
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+ }
+ else {
+ bchunk_list_append_data(info, bs_mem, chunk_list, &data[i_prev], i - i_prev);
+ ASSERT_CHUNKLIST_SIZE(chunk_list, i);
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+ }
+
+ cref = cref->next;
+
+ i_prev = i;
+ }
+ }
+ else if ((data_len - i_prev >= info->chunk_byte_size) &&
+ (chunk_list_reference->chunk_refs_len >= chunk_list_reference_skip_len) &&
+ (chunk_list_reference->chunk_refs.first != NULL))
+ {
+
+ /* --------------------------------------------------------------------
+ * Non-Aligned Chunk De-Duplication */
+
+ /* only create a table if we have at least one chunk to search
+ * otherwise just make a new one.
+ *
+ * Support re-arranged chunks */
+
+#ifdef USE_HASH_TABLE_ACCUMULATE
+ size_t i_table_start = i_prev;
+ const size_t table_hash_array_len = (data_len - i_prev) / info->chunk_stride;
+ hash_key *table_hash_array = MEM_mallocN(sizeof(*table_hash_array) * table_hash_array_len, __func__);
+ hash_array_from_data(info, &data[i_prev], data_len - i_prev, table_hash_array);
+
+ hash_accum(table_hash_array, table_hash_array_len, info->accum_steps);
+#else
+ /* dummy vars */
+ uint i_table_start = 0;
+ hash_key *table_hash_array = NULL;
+#endif
+
+ const uint chunk_list_reference_remaining_len =
+ (chunk_list_reference->chunk_refs_len - chunk_list_reference_skip_len) + 1;
+ BTableRef *table_ref_stack = MEM_mallocN(chunk_list_reference_remaining_len * sizeof(BTableRef), __func__);
+ uint table_ref_stack_n = 0;
+
+ const size_t table_len = chunk_list_reference_remaining_len * BCHUNK_HASH_TABLE_MUL;
+ BTableRef **table = MEM_callocN(table_len * sizeof(*table), __func__);
+
+ /* table_make - inline
+ * include one matching chunk, to allow for repeating values */
+ {
+#ifdef USE_HASH_TABLE_ACCUMULATE
+ const size_t hash_store_len = info->accum_read_ahead_len;
+ hash_key *hash_store = MEM_mallocN(sizeof(hash_key) * hash_store_len, __func__);
+#endif
+
+ const BChunkRef *cref;
+ size_t chunk_list_reference_bytes_remaining =
+ chunk_list_reference->total_size - chunk_list_reference_skip_bytes;
+
+ if (cref_match_first) {
+ cref = cref_match_first;
+ chunk_list_reference_bytes_remaining += cref->link->data_len;
+ }
+ else {
+ cref = chunk_list_reference->chunk_refs.first;
+ }
+
+#ifdef USE_PARANOID_CHECKS
+ {
+ size_t test_bytes_len = 0;
+ const BChunkRef *cr = cref;
+ while (cr != chunk_list_reference_last) {
+ test_bytes_len += cr->link->data_len;
+ cr = cr->next;
+ }
+ BLI_assert(test_bytes_len == chunk_list_reference_bytes_remaining);
+ }
+#endif
+
+ while ((cref != chunk_list_reference_last) &&
+ (chunk_list_reference_bytes_remaining >= info->accum_read_ahead_bytes))
+ {
+ hash_key key = key_from_chunk_ref(info, cref
+
+#ifdef USE_HASH_TABLE_ACCUMULATE
+ , hash_store, hash_store_len
+#endif
+ );
+ size_t key_index = (size_t)(key % (hash_key)table_len);
+ BTableRef *tref_prev = table[key_index];
+ BLI_assert(table_ref_stack_n < chunk_list_reference_remaining_len);
+ BTableRef *tref = &table_ref_stack[table_ref_stack_n++];
+ tref->cref = cref;
+ tref->next = tref_prev;
+ table[key_index] = tref;
+
+ chunk_list_reference_bytes_remaining -= cref->link->data_len;
+ cref = cref->next;
+ }
+
+ BLI_assert(table_ref_stack_n <= chunk_list_reference_remaining_len);
+
+#ifdef USE_HASH_TABLE_ACCUMULATE
+ MEM_freeN(hash_store);
+#endif
+ }
+ /* done making the table */
+
+ BLI_assert(i_prev <= data_len);
+ for (size_t i = i_prev; i < data_len; ) {
+ /* Assumes exiting chunk isnt a match! */
+
+ const BChunkRef *cref_found = table_lookup(
+ info,
+ table, table_len, i_table_start,
+ data, data_len, i, table_hash_array);
+ if (cref_found != NULL) {
+ BLI_assert(i < data_len);
+ if (i != i_prev) {
+ size_t i_step = MIN2(i_prev + info->chunk_byte_size, data_len);
+ BLI_assert(i_step <= data_len);
+
+ while (i_prev != i) {
+ i_step = MIN2(i_step, i);
+ const ubyte *data_slice = &data[i_prev];
+ const size_t data_slice_len = i_step - i_prev;
+ /* First add all previous chunks! */
+ i_prev += data_slice_len;
+ bchunk_list_append_data(info, bs_mem, chunk_list, data_slice, data_slice_len);
+ BLI_assert(i_prev <= data_len);
+ ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev);
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+ i_step += info->chunk_byte_size;
+ }
+ }
+
+ /* now add the reference chunk */
+ {
+ BChunk *chunk_found = cref_found->link;
+ i += chunk_found->data_len;
+ bchunk_list_append(info, bs_mem, chunk_list, chunk_found);
+ }
+ i_prev = i;
+ BLI_assert(i_prev <= data_len);
+ ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev);
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+
+ /* its likely that the next chunk in the list will be a match, so check it! */
+ while ((cref_found->next != NULL) &&
+ (cref_found->next != chunk_list_reference_last))
+ {
+ cref_found = cref_found->next;
+ BChunk *chunk_found = cref_found->link;
+
+ if (bchunk_data_compare(chunk_found, data, data_len, i_prev)) {
+ /* may be useful to remove table data, assuming we dont have repeating memory
+ * where it would be useful to re-use chunks. */
+ i += chunk_found->data_len;
+ bchunk_list_append(info, bs_mem, chunk_list, chunk_found);
+ /* chunk_found may be freed! */
+ i_prev = i;
+ BLI_assert(i_prev <= data_len);
+ ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev);
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+ }
+ else {
+ break;
+ }
+ }
+ }
+ else {
+ i = i + info->chunk_stride;
+ }
+ }
+
+#ifdef USE_HASH_TABLE_ACCUMULATE
+ MEM_freeN(table_hash_array);
+#endif
+ MEM_freeN(table);
+ MEM_freeN(table_ref_stack);
+
+ /* End Table Lookup
+ * ---------------- */
+ }
+
+ ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev);
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+
+ /* -----------------------------------------------------------------------
+ * No Duplicates to copy, write new chunks
+ *
+ * Trailing chunks, no matches found in table lookup above.
+ * Write all new data. */
+ BLI_assert(i_prev <= data_len);
+ while (i_prev != data_len) {
+ size_t i = i_prev + info->chunk_byte_size;
+ i = MIN2(i, data_len);
+ BLI_assert(i != i_prev);
+ bchunk_list_append_data(info, bs_mem, chunk_list, &data[i_prev], i - i_prev);
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+ i_prev = i;
+ }
+
+ BLI_assert(i_prev == data_len);
+
+#ifdef USE_FASTPATH_CHUNKS_LAST
+ if (chunk_list_reference_last != NULL) {
+ /* write chunk_list_reference_last since it hasn't been written yet */
+ const BChunkRef *cref = chunk_list_reference_last;
+ while (cref != NULL) {
+ BChunk *chunk = cref->link;
+ // BLI_assert(bchunk_data_compare(chunk, data, data_len, i_prev));
+ i_prev += chunk->data_len;
+ /* use simple since we assume the references chunks have already been sized correctly. */
+ bchunk_list_append_only(bs_mem, chunk_list, chunk);
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+ cref = cref->next;
+ }
+ }
+#endif
+
+#undef data_len_original
+
+ BLI_assert(i_prev == data_len_original);
+
+ /* check we're the correct size and that we didn't accidentally modify the reference */
+ ASSERT_CHUNKLIST_SIZE(chunk_list, data_len_original);
+ ASSERT_CHUNKLIST_SIZE(chunk_list_reference, chunk_list_reference->total_size);
+
+ ASSERT_CHUNKLIST_DATA(chunk_list, data);
+
+ return chunk_list;
+}
+/* end private API */
+
+/** \} */
+
+
+/** \name Main Array Storage API
+ * \{ */
+
+
+/**
+ * Create a new array store, which can store any number of arrays
+ * as long as their stride matches.
+ *
+ * \param stride: ``sizeof()`` each element,
+ *
+ * \note while a stride of ``1`` will always work,
+ * its less efficient since duplicate chunks of memory will be searched
+ * at positions unaligned with the array data.
+ *
+ * \param chunk_count: Number of elements to split each chunk into.
+ * - A small value increases the ability to de-duplicate chunks,
+ * but adds overhead by increasing the number of chunks to look-up when searching for duplicates,
+ * as well as some overhead constructing the original array again, with more calls to ``memcpy``.
+ * - Larger values reduce the *book keeping* overhead,
+ * but increase the chance a small, isolated change will cause a larger amount of data to be duplicated.
+ *
+ * \return A new array store, to be freed with #BLI_array_store_destroy.
+ */
+BArrayStore *BLI_array_store_create(
+ uint stride,
+ uint chunk_count)
+{
+ BArrayStore *bs = MEM_callocN(sizeof(BArrayStore), __func__);
+
+ bs->info.chunk_stride = stride;
+ bs->info.chunk_count = chunk_count;
+
+ bs->info.chunk_byte_size = chunk_count * stride;
+#ifdef USE_MERGE_CHUNKS
+ bs->info.chunk_byte_size_min = MAX2(1u, chunk_count / BCHUNK_SIZE_MIN_DIV) * stride;
+#endif
+
+#ifdef USE_HASH_TABLE_ACCUMULATE
+ bs->info.accum_steps = BCHUNK_HASH_TABLE_ACCUMULATE_STEPS - 1;
+ /* Triangle number, identifying now much read-ahead we need:
+ * https://en.wikipedia.org/wiki/Triangular_number (+ 1) */
+ bs->info.accum_read_ahead_len = (uint)((((bs->info.accum_steps * (bs->info.accum_steps + 1))) / 2) + 1);
+ bs->info.accum_read_ahead_bytes = bs->info.accum_read_ahead_len * stride;
+#else
+ bs->info.accum_read_ahead_bytes = BCHUNK_HASH_LEN * stride;
+#endif
+
+ bs->memory.chunk_list = BLI_mempool_create(sizeof(BChunkList), 0, 512, BLI_MEMPOOL_NOP);
+ bs->memory.chunk_ref = BLI_mempool_create(sizeof(BChunkRef), 0, 512, BLI_MEMPOOL_NOP);
+ /* allow iteration to simplify freeing, otherwise its not needed
+ * (we could loop over all states as an alternative). */
+ bs->memory.chunk = BLI_mempool_create(sizeof(BChunk), 0, 512, BLI_MEMPOOL_ALLOW_ITER);
+
+ return bs;
+}
+
+static void array_store_free_data(BArrayStore *bs)
+{
+ /* free chunk data */
+ {
+ BLI_mempool_iter iter;
+ BChunk *chunk;
+ BLI_mempool_iternew(bs->memory.chunk, &iter);
+ while ((chunk = BLI_mempool_iterstep(&iter))) {
+ BLI_assert(chunk->users > 0);
+ MEM_freeN((void *)chunk->data);
+ }
+ }
+
+ /* free states */
+ for (BArrayState *state = bs->states.first, *state_next; state; state = state_next) {
+ state_next = state->next;
+ MEM_freeN(state);
+ }
+}
+
+/**
+ * Free the #BArrayStore, including all states and chunks.
+ */
+void BLI_array_store_destroy(
+ BArrayStore *bs)
+{
+ array_store_free_data(bs);
+
+ BLI_mempool_destroy(bs->memory.chunk_list);
+ BLI_mempool_destroy(bs->memory.chunk_ref);
+ BLI_mempool_destroy(bs->memory.chunk);
+
+ MEM_freeN(bs);
+}
+
+/**
+ * Clear all contents, allowing reuse of \a bs.
+ */
+void BLI_array_store_clear(
+ BArrayStore *bs)
+{
+ array_store_free_data(bs);
+
+ BLI_listbase_clear(&bs->states);
+
+ BLI_mempool_clear(bs->memory.chunk_list);
+ BLI_mempool_clear(bs->memory.chunk_ref);
+ BLI_mempool_clear(bs->memory.chunk);
+}
+
+/** \name BArrayStore Statistics
+ * \{ */
+
+/**
+ * \return the total amount of memory that would be used by getting the arrays for all states.
+ */
+size_t BLI_array_store_calc_size_expanded_get(
+ const BArrayStore *bs)
+{
+ size_t size_accum = 0;
+ for (const BArrayState *state = bs->states.first; state; state = state->next) {
+ size_accum += state->chunk_list->total_size;
+ }
+ return size_accum;
+}
+
+/**
+ * \return the amount of memory used by all #BChunk.data
+ * (duplicate chunks are only counted once).
+ */
+size_t BLI_array_store_calc_size_compacted_get(
+ const BArrayStore *bs)
+{
+ size_t size_total = 0;
+ BLI_mempool_iter iter;
+ BChunk *chunk;
+ BLI_mempool_iternew(bs->memory.chunk, &iter);
+ while ((chunk = BLI_mempool_iterstep(&iter))) {
+ BLI_assert(chunk->users > 0);
+ size_total += (size_t)chunk->data_len;
+ }
+ return size_total;
+}
+
+/** \} */
+
+
+/** \name BArrayState Access
+ * \{ */
+
+/**
+ *
+ * \param data: Data used to create
+ * \param state_reference: The state to use as a reference when adding the new state,
+ * typically this is the previous state,
+ * however it can be any previously created state from this \a bs.
+ *
+ * \return The new state, which is used by the caller as a handle to get back the contents of \a data.
+ * This may be removed using #BLI_array_store_state_remove,
+ * otherwise it will be removed with #BLI_array_store_destroy.
+ */
+BArrayState *BLI_array_store_state_add(
+ BArrayStore *bs,
+ const void *data, const size_t data_len,
+ const BArrayState *state_reference)
+{
+ /* ensure we're aligned to the stride */
+ BLI_assert((data_len % bs->info.chunk_stride) == 0);
+
+#ifdef USE_PARANOID_CHECKS
+ if (state_reference) {
+ BLI_assert(BLI_findindex(&bs->states, state_reference) != -1);
+ }
+#endif
+
+ BChunkList *chunk_list;
+ if (state_reference) {
+ chunk_list = bchunk_list_from_data_merge(
+ &bs->info, &bs->memory,
+ (const ubyte *)data, data_len,
+ /* re-use reference chunks */
+ state_reference->chunk_list);
+ }
+ else {
+ chunk_list = bchunk_list_new(&bs->memory, data_len);
+ bchunk_list_fill_from_array(
+ &bs->info, &bs->memory,
+ chunk_list,
+ (const ubyte *)data, data_len);
+ }
+
+ chunk_list->users += 1;
+
+ BArrayState *state = MEM_callocN(sizeof(BArrayState), __func__);
+ state->chunk_list = chunk_list;
+
+ BLI_addtail(&bs->states, state);
+
+#ifdef USE_PARANOID_CHECKS
+ {
+ size_t data_test_len;
+ void *data_test = BLI_array_store_state_data_get_alloc(state, &data_test_len);
+ BLI_assert(data_test_len == data_len);
+ BLI_assert(memcmp(data_test, data, data_len) == 0);
+ MEM_freeN(data_test);
+ }
+#endif
+
+ return state;
+}
+
+/**
+ * Remove a state and free any unused #BChunk data.
+ *
+ * The states can be freed in any order.
+ */
+void BLI_array_store_state_remove(
+ BArrayStore *bs,
+ BArrayState *state)
+{
+#ifdef USE_PARANOID_CHECKS
+ BLI_assert(BLI_findindex(&bs->states, state) != -1);
+#endif
+
+ bchunk_list_decref(&bs->memory, state->chunk_list);
+ BLI_remlink(&bs->states, state);
+
+ MEM_freeN(state);
+}
+
+/**
+ * \return the expanded size of the array,
+ * use this to know how much memory to allocate #BLI_array_store_state_data_get's argument.
+ */
+size_t BLI_array_store_state_size_get(
+ BArrayState *state)
+{
+ return state->chunk_list->total_size;
+}
+
+/**
+ * Fill in existing allocated memory with the contents of \a state.
+ */
+void BLI_array_store_state_data_get(
+ BArrayState *state,
+ void *data)
+{
+#ifdef USE_PARANOID_CHECKS
+ size_t data_test_len = 0;
+ for (BChunkRef *cref = state->chunk_list->chunk_refs.first; cref; cref = cref->next) {
+ data_test_len += cref->link->data_len;
+ }
+ BLI_assert(data_test_len == state->chunk_list->total_size);
+#endif
+
+ ubyte *data_step = (ubyte *)data;
+ for (BChunkRef *cref = state->chunk_list->chunk_refs.first; cref; cref = cref->next) {
+ BLI_assert(cref->link->users > 0);
+ memcpy(data_step, cref->link->data, cref->link->data_len);
+ data_step += cref->link->data_len;
+ }
+}
+
+/**
+ * Allocate an array for \a state and return it.
+ */
+void *BLI_array_store_state_data_get_alloc(
+ BArrayState *state,
+ size_t *r_data_len)
+{
+ void *data = MEM_mallocN(state->chunk_list->total_size, __func__);
+ BLI_array_store_state_data_get(state, data);
+ *r_data_len = state->chunk_list->total_size;
+ return data;
+}
+
+/** \} */
+
+
+/** \name Debigging API (for testing).
+ * \{ */
+
+/* only for test validation */
+static size_t bchunk_list_size(const BChunkList *chunk_list)
+{
+ size_t total_size = 0;
+ for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) {
+ total_size += cref->link->data_len;
+ }
+ return total_size;
+}
+
+bool BLI_array_store_is_valid(
+ BArrayStore *bs)
+{
+ bool ok = true;
+
+ /* Check Length
+ * ------------ */
+
+ for (BArrayState *state = bs->states.first; state; state = state->next) {
+ BChunkList *chunk_list = state->chunk_list;
+ if (!(bchunk_list_size(chunk_list) == chunk_list->total_size)) {
+ return false;
+ }
+ }
+
+ {
+ BLI_mempool_iter iter;
+ BChunk *chunk;
+ BLI_mempool_iternew(bs->memory.chunk, &iter);
+ while ((chunk = BLI_mempool_iterstep(&iter))) {
+ if (!(MEM_allocN_len(chunk->data) >= chunk->data_len)) {
+ return false;
+ }
+ }
+ }
+
+ /* Check User Count & Lost References
+ * ---------------------------------- */
+ {
+ GHashIterator gh_iter;
+
+#define GHASH_PTR_ADD_USER(gh, pt) \
+ { \
+ void **val; \
+ if (BLI_ghash_ensure_p((gh), (pt), &val)) { \
+ *((int *)val) += 1; \
+ } \
+ else { \
+ *((int *)val) = 1; \
+ } \
+ } ((void)0)
+
+
+ /* count chunk_list's */
+ int totrefs = 0;
+ GHash *chunk_list_map = BLI_ghash_ptr_new(__func__);
+ for (BArrayState *state = bs->states.first; state; state = state->next) {
+ GHASH_PTR_ADD_USER(chunk_list_map, state->chunk_list);
+ }
+ GHASH_ITER (gh_iter, chunk_list_map) {
+ const struct BChunkList *chunk_list = BLI_ghashIterator_getKey(&gh_iter);
+ const int users = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));
+ if (!(chunk_list->users == users)) {
+ ok = false;
+ goto user_finally;
+ }
+ }
+ if (!(BLI_mempool_count(bs->memory.chunk_list) == (int)BLI_ghash_size(chunk_list_map))) {
+ ok = false;
+ goto user_finally;
+ }
+
+ /* count chunk's */
+ GHash *chunk_map = BLI_ghash_ptr_new(__func__);
+ GHASH_ITER (gh_iter, chunk_list_map) {
+ const struct BChunkList *chunk_list = BLI_ghashIterator_getKey(&gh_iter);
+ for (const BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) {
+ GHASH_PTR_ADD_USER(chunk_map, cref->link);
+ totrefs += 1;
+ }
+ }
+ if (!(BLI_mempool_count(bs->memory.chunk) == (int)BLI_ghash_size(chunk_map))) {
+ ok = false;
+ goto user_finally;
+ }
+ if (!(BLI_mempool_count(bs->memory.chunk_ref) == totrefs)) {
+ ok = false;
+ goto user_finally;
+ }
+
+ GHASH_ITER (gh_iter, chunk_map) {
+ const struct BChunk *chunk = BLI_ghashIterator_getKey(&gh_iter);
+ const int users = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter));
+ if (!(chunk->users == users)) {
+ ok = false;
+ goto user_finally;
+ }
+ }
+
+#undef GHASH_PTR_ADD_USER
+
+user_finally:
+ BLI_ghash_free(chunk_list_map, NULL, NULL);
+ BLI_ghash_free(chunk_map, NULL, NULL);
+ }
+
+
+ return ok;
+ /* TODO, dangling pointer checks */
+}
+
+/** \} */
diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c
index c3a0c44d7c5..f834c5b4c74 100644
--- a/source/blender/blenlib/intern/noise.c
+++ b/source/blender/blenlib/intern/noise.c
@@ -1048,8 +1048,8 @@ static float noise3_perlin(float vec[3])
b01 = p[i + by1];
b11 = p[j + by1];
-#define VALUE_AT(rx, ry, rz) (rx * q[0] + ry * q[1] + rz * q[2])
-#define SURVE(t) (t * t * (3.0f - 2.0f * t))
+#define VALUE_AT(rx, ry, rz) ((rx) * q[0] + (ry) * q[1] + (rz) * q[2])
+#define SURVE(t) ((t) * (t) * (3.0f - 2.0f * (t)))
/* lerp moved to improved perlin above */
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 7b102c9283b..bb61f66e267 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -804,10 +804,10 @@ void BM_mesh_bm_to_me(
BMEditSelection *selected;
me->totselect = BLI_listbase_count(&(bm->selected));
- if (me->mselect) MEM_freeN(me->mselect);
-
- me->mselect = MEM_callocN(sizeof(MSelect) * me->totselect, "Mesh selection history");
-
+ MEM_SAFE_FREE(me->mselect);
+ if (me->totselect != 0) {
+ me->mselect = MEM_mallocN(sizeof(MSelect) * me->totselect, "Mesh selection history");
+ }
for (i = 0, selected = bm->selected.first; selected; i++, selected = selected->next) {
if (selected->htype == BM_VERT) {
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 5a7788c0b62..f7e3622e53c 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -345,6 +345,36 @@ static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e)
return NULL;
}
+/* return count of edges between e1 and e2 when going around bv CCW */
+static int count_ccw_edges_between(EdgeHalf *e1, EdgeHalf *e2)
+{
+ int cnt = 0;
+ EdgeHalf *e = e1;
+
+ do {
+ if (e == e2)
+ break;
+ e = e->next;
+ cnt++;
+ } while (e != e1);
+ return cnt;
+}
+
+/* Assume bme1 and bme2 both share some vert. Do they share a face?
+ * If they share a face then there is some loop around bme1 that is in a face
+ * where the next or previous edge in the face must be bme2. */
+static bool edges_face_connected_at_vert(BMEdge *bme1, BMEdge *bme2)
+{
+ BMLoop *l;
+ BMIter iter;
+
+ BM_ITER_ELEM(l, &iter, bme1, BM_LOOPS_OF_EDGE) {
+ if (l->prev->e == bme2 || l->next->e == bme2)
+ return true;
+ }
+ return false;
+}
+
/* Return a good representative face (for materials, etc.) for faces
* created around/near BoundVert v.
* Sometimes care about a second choice, if there is one.
@@ -1557,7 +1587,7 @@ static void build_boundary_vertex_only(BevelParams *bp, BevVert *bv, bool constr
if (construct) {
v = add_new_bound_vert(bp->mem_arena, vm, co);
v->efirst = v->elast = e;
- e->leftv = v;
+ e->leftv = e->rightv = v;
}
else {
adjust_bound_vert(e->leftv, co);
@@ -1637,7 +1667,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf
v->efirst = e->prev;
v->elast = v->ebev = e;
e->leftv = v;
- e->prev->leftv = v;
+ e->prev->leftv = e->prev->rightv = v;
}
else {
adjust_bound_vert(e->leftv, co);
@@ -1648,7 +1678,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf
v = add_new_bound_vert(mem_arena, vm, co);
v->efirst = e->prev;
v->elast = e;
- e->leftv = v;
+ e->leftv = e->rightv = v;
e->prev->rightv = v;
}
else {
@@ -1661,7 +1691,7 @@ static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf
if (construct) {
v = add_new_bound_vert(mem_arena, vm, co);
v->efirst = v->elast = e;
- e->leftv = v;
+ e->leftv = e->rightv = v;
}
else {
adjust_bound_vert(e->leftv, co);
@@ -3237,6 +3267,11 @@ static void build_vmesh(BevelParams *bp, BMesh *bm, BevVert *bv)
if (!weld)
create_mesh_bmvert(bm, vm, i, 0, k, bv->v);
}
+ else if (n == 2 && !v->ebev && vm->mesh_kind != M_ADJ) {
+ /* case of one edge beveled and this is the v without ebev */
+ /* want to copy the verts from other v, in reverse order */
+ copy_mesh_vert(vm, i, 0, k, 1 - i, 0, ns - k);
+ }
}
} while ((v = v->next) != vm->boundstart);
@@ -3305,6 +3340,219 @@ static float edge_face_angle(EdgeHalf *e)
#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_ELEM_API_FLAG_DISABLE( (bme), _FLAG_OVERLAP)
#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_ELEM_API_FLAG_TEST( (bme), _FLAG_OVERLAP)
+/* Try to extend the bv->edges[] array beyond i by finding more successor edges.
+ * This is a possibly exponential-time search, but it is only exponential in the number
+ * of "internal faces" at a vertex -- i.e., faces that bridge between the edges that naturally
+ * form a manifold cap around bv. It is rare to have more than one of these, so unlikely
+ * that the exponential time case will be hit in practice.
+ * Returns the new index i' where bv->edges[i'] ends the best path found.
+ * The path will have the tags of all of its edges set. */
+static int bevel_edge_order_extend(BMesh *bm, BevVert *bv, int i)
+{
+ BMEdge *bme, *bme2, *nextbme;
+ BMLoop *l;
+ BMIter iter;
+ int j, tryj, bestj, nsucs, sucindex, k;
+ BMEdge **sucs = NULL;
+ BMEdge **save_path = NULL;
+ BLI_array_staticdeclare(sucs, 4); /* likely very few faces attached to same edge */
+ BLI_array_staticdeclare(save_path, BM_DEFAULT_NGON_STACK_SIZE);
+
+ bme = bv->edges[i].e;
+ /* fill sucs with all unmarked edges of bmes */
+ BM_ITER_ELEM(l, &iter, bme, BM_LOOPS_OF_EDGE) {
+ bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
+ if (!BM_BEVEL_EDGE_TAG_TEST(bme2)) {
+ BLI_array_append(sucs, bme2);
+ }
+ }
+ nsucs = BLI_array_count(sucs);
+
+ bestj = j = i;
+ for (sucindex = 0; sucindex < nsucs; sucindex++) {
+ nextbme = sucs[sucindex];
+ BLI_assert(nextbme != NULL);
+ BLI_assert(!BM_BEVEL_EDGE_TAG_TEST(nextbme));
+ BLI_assert(j + 1 < bv->edgecount);
+ bv->edges[j + 1].e = nextbme;
+ BM_BEVEL_EDGE_TAG_ENABLE(nextbme);
+ tryj = bevel_edge_order_extend(bm, bv, j + 1);
+ if (tryj > bestj || (tryj == bestj && edges_face_connected_at_vert(bv->edges[tryj].e, bv->edges[0].e))) {
+ bestj = tryj;
+ BLI_array_empty(save_path);
+ for (k = j + 1; k <= bestj; k++) {
+ BLI_array_append(save_path, bv->edges[k].e);
+ }
+ }
+ /* now reset to path only-going-to-j state */
+ for (k = j + 1; k <= tryj; k++) {
+ BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
+ bv->edges[k].e = NULL;
+ }
+ }
+ /* at this point we should be back at invariant on entrance: path up to j */
+ if (bestj > j) {
+ /* save_path should have from j + 1 to bestj inclusive edges to add to edges[] before returning */
+ for (k = j + 1; k <= bestj; k++) {
+ BLI_assert(save_path[k - (j + 1)] != NULL);
+ bv->edges[k].e = save_path[k - (j + 1)];
+ BM_BEVEL_EDGE_TAG_ENABLE(bv->edges[k].e);
+ }
+ }
+ BLI_array_free(sucs);
+ BLI_array_free(save_path);
+ return bestj;
+}
+
+/* See if we have usual case for bevel edge order:
+ * there is an ordering such that all the faces are between
+ * successive edges and form a manifold "cap" at bv.
+ * If this is the case, set bv->edges to such an order
+ * and return true; else return unmark any partial path and return false.
+ * Assume the first edge is already in bv->edges[0].e and it is tagged. */
+#ifdef FASTER_FASTORDER
+/* The alternative older code is O(n^2) where n = # of edges incident to bv->v.
+ * This implementation is O(n * m) where m = average number of faces attached to an edge incident to bv->v,
+ * which is almost certainly a small constant except in very strange cases. But this code produces different
+ * choices of ordering than the legacy system, leading to differences in vertex orders etc. in user models,
+ * so for now will continue to use the legacy code. */
+static bool fast_bevel_edge_order(BevVert *bv)
+{
+ int j, k, nsucs;
+ BMEdge *bme, *bme2, *bmenext;
+ BMIter iter;
+ BMLoop *l;
+
+ for (j = 1; j < bv->edgecount; j++) {
+ bme = bv->edges[j - 1].e;
+ bmenext = NULL;
+ nsucs = 0;
+ BM_ITER_ELEM(l, &iter, bme, BM_LOOPS_OF_EDGE) {
+ bme2 = (l->v == bv->v) ? l->prev->e : l->next->e;
+ if (!BM_BEVEL_EDGE_TAG_TEST(bme2)) {
+ nsucs++;
+ if (bmenext == NULL)
+ bmenext = bme2;
+ }
+ }
+ if (nsucs == 0 || (nsucs == 2 && j != 1) || nsucs > 2 ||
+ (j == bv->edgecount - 1 && !edges_face_connected_at_vert(bmenext, bv->edges[0].e)))
+ {
+ for (k = 1; k < j; k++) {
+ BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
+ bv->edges[k].e = NULL;
+ }
+ return false;
+ }
+ bv->edges[j].e = bmenext;
+ BM_BEVEL_EDGE_TAG_ENABLE(bmenext);
+ }
+ return true;
+}
+#else
+static bool fast_bevel_edge_order(BevVert *bv)
+{
+ BMEdge *bme, *bme2, *first_suc;
+ BMIter iter, iter2;
+ BMFace *f;
+ EdgeHalf *e;
+ int i, k, ntot, num_shared_face;
+
+ ntot = bv->edgecount;
+
+ /* add edges to bv->edges in order that keeps adjacent edges sharing
+ * a unique face, if possible */
+ e = &bv->edges[0];
+ bme = e->e;
+ if (!bme->l)
+ return false;
+ for (i = 1; i < ntot; i++) {
+ /* find an unflagged edge bme2 that shares a face f with previous bme */
+ num_shared_face = 0;
+ first_suc = NULL; /* keep track of first successor to match legacy behavior */
+ BM_ITER_ELEM (bme2, &iter, bv->v, BM_EDGES_OF_VERT) {
+ if (BM_BEVEL_EDGE_TAG_TEST(bme2))
+ continue;
+ BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) {
+ if (BM_face_edge_share_loop(f, bme)) {
+ num_shared_face++;
+ if (first_suc == NULL)
+ first_suc = bme2;
+ }
+ }
+ if (num_shared_face >= 3)
+ break;
+ }
+ if (num_shared_face == 1 || (i == 1 && num_shared_face == 2)) {
+ e = &bv->edges[i];
+ e->e = bme = first_suc;
+ BM_BEVEL_EDGE_TAG_ENABLE(bme);
+ }
+ else {
+ for (k = 1; k < i; k++) {
+ BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
+ bv->edges[k].e = NULL;
+ }
+ return false;
+ }
+ }
+ return true;
+}
+#endif
+
+/* Fill in bv->edges with a good ordering of non-wire edges around bv->v.
+ * Use only edges where BM_BEVEL_EDGE_TAG is disabled so far
+ * (if edge beveling, others are wire).
+ * first_bme is a good edge to start with.*/
+static void find_bevel_edge_order(BMesh *bm, BevVert *bv, BMEdge *first_bme)
+{
+ BMEdge *bme, *bme2;
+ BMIter iter;
+ BMFace *f;
+ EdgeHalf *e;
+ EdgeHalf *e2;
+ BMLoop *l;
+ int i, ntot;
+
+ ntot = bv->edgecount;
+ i = 0;
+ for (;;) {
+ BLI_assert(first_bme != NULL);
+ bv->edges[i].e = first_bme;
+ BM_BEVEL_EDGE_TAG_ENABLE(first_bme);
+ if (fast_bevel_edge_order(bv))
+ break;
+ i = bevel_edge_order_extend(bm, bv, i);
+ i++;
+ if (i >= bv->edgecount)
+ break;
+ /* Not done yet: find a new first_bme */
+ first_bme = NULL;
+ BM_ITER_ELEM(bme, &iter, bv->v, BM_EDGES_OF_VERT) {
+ if (BM_BEVEL_EDGE_TAG_TEST(bme))
+ continue;
+ if (!first_bme)
+ first_bme = bme;
+ if (BM_edge_face_count(bme) == 1) {
+ first_bme = bme;
+ break;
+ }
+ }
+ }
+ /* now fill in the faces ... */
+ for (i = 0; i < ntot; i++) {
+ e = &bv->edges[i];
+ e2 = (i == bv->edgecount - 1) ? &bv->edges[0] : &bv->edges[i + 1];
+ bme = e->e;
+ bme2 = e2->e;
+ BM_ITER_ELEM(l, &iter, bme, BM_LOOPS_OF_EDGE) {
+ f = l->f;
+ if ((l->prev->e == bme2 || l->next->e == bme2) && !e->fnext && !e2->fprev)
+ e->fnext = e2->fprev = f;
+ }
+ }
+}
+
/*
* Construction around the vertex
*/
@@ -3312,13 +3560,12 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
{
BMEdge *bme;
BevVert *bv;
- BMEdge *bme2, *unflagged_bme, *first_bme;
- BMFace *f;
+ BMEdge *first_bme;
BMVert *v1, *v2;
- BMIter iter, iter2;
+ BMIter iter;
EdgeHalf *e;
float weight, z;
- int i, found_shared_face, ccw_test_sum;
+ int i, ccw_test_sum;
int nsel = 0;
int ntot = 0;
int nwire = 0;
@@ -3398,47 +3645,12 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
}
BLI_ghash_insert(bp->vert_hash, v, bv);
- /* add edges to bv->edges in order that keeps adjacent edges sharing
- * a face, if possible */
- i = 0;
+ find_bevel_edge_order(bm, bv, first_bme);
- bme = first_bme;
- BM_BEVEL_EDGE_TAG_ENABLE(bme);
- e = &bv->edges[0];
- e->e = bme;
+ /* fill in other attributes of EdgeHalfs */
for (i = 0; i < ntot; i++) {
- if (i > 0) {
- /* find an unflagged edge bme2 that shares a face f with previous bme */
- found_shared_face = 0;
- unflagged_bme = NULL;
- BM_ITER_ELEM (bme2, &iter, v, BM_EDGES_OF_VERT) {
- if (BM_BEVEL_EDGE_TAG_TEST(bme2))
- continue;
- if (!unflagged_bme)
- unflagged_bme = bme2;
- if (!bme->l)
- continue;
- BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) {
- if (BM_face_edge_share_loop(f, bme)) {
- found_shared_face = 1;
- break;
- }
- }
- if (found_shared_face)
- break;
- }
- e = &bv->edges[i];
- if (found_shared_face) {
- e->e = bme2;
- e->fprev = f;
- bv->edges[i - 1].fnext = f;
- }
- else {
- e->e = unflagged_bme;
- }
- }
+ e = &bv->edges[i];
bme = e->e;
- BM_BEVEL_EDGE_TAG_ENABLE(bme);
if (BM_elem_flag_test(bme, BM_ELEM_TAG) && !bp->vertex_only) {
e->is_bev = true;
e->seg = bp->seg;
@@ -3449,16 +3661,6 @@ static BevVert *bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v)
}
e->is_rev = (bme->v2 == v);
}
- /* find wrap-around shared face */
- BM_ITER_ELEM (f, &iter2, bme, BM_FACES_OF_EDGE) {
- if (bv->edges[0].e->l && BM_face_edge_share_loop(f, bv->edges[0].e)) {
- if (bv->edges[0].fnext == f)
- continue; /* if two shared faces, want the other one now */
- bv->edges[ntot - 1].fnext = f;
- bv->edges[0].fprev = f;
- break;
- }
- }
/* now done with tag flag */
BM_ITER_ELEM (bme, &iter, v, BM_EDGES_OF_VERT) {
@@ -3586,6 +3788,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
VMesh *vm;
int i, k, n;
bool do_rebuild = false;
+ bool go_ccw, corner3special;
BMVert *bmv;
BMEdge *bme, *bme_new, *bme_prev;
BMFace *f_new;
@@ -3600,47 +3803,88 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
lprev = l->prev;
bv = find_bevvert(bp, l->v);
+ vm = bv->vmesh;
e = find_edge_half(bv, l->e);
bme = e->e;
eprev = find_edge_half(bv, lprev->e);
BLI_assert(e != NULL && eprev != NULL);
- vstart = eprev->leftv;
- if (e->is_bev)
- vend = e->rightv;
- else
+
+ /* which direction around our vertex do we travel to match orientation of f? */
+ if (e->prev == eprev) {
+ if (eprev->prev == e) {
+ /* valence 2 vertex: use f is one of e->fnext or e->fprev to break tie */
+ go_ccw = (e->fnext != f);
+ }
+ else {
+ go_ccw = true; /* going ccw around bv to trace this corner */
+ }
+ }
+ else if (eprev->prev == e) {
+ go_ccw = false; /* going cw around bv to trace this corner */
+ }
+ else {
+ /* edges in face are non-contiguous in our ordering around bv.
+ * Which way should we go when going from eprev to e? */
+ if (count_ccw_edges_between(eprev, e) < count_ccw_edges_between(e, eprev)) {
+ /* go counterclockewise from eprev to e */
+ go_ccw = true;
+ }
+ else {
+ /* go clockwise from eprev to e */
+ go_ccw = false;
+ }
+ }
+ if (go_ccw) {
+ vstart = eprev->rightv;
vend = e->leftv;
+ }
+ else {
+ vstart = eprev->leftv;
+ vend = e->rightv;
+ }
+ BLI_assert(vstart != NULL && vend != NULL);
v = vstart;
- vm = bv->vmesh;
BLI_array_append(vv, v->nv.v);
BLI_array_append(ee, bme);
+ /* check for special case: multisegment 3rd face opposite a beveled edge with no vmesh */
+ corner3special = (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev);
while (v != vend) {
- if (vm->mesh_kind == M_NONE && v->ebev && v->ebev->seg > 1 && v->ebev != e && v->ebev != eprev) {
- /* case of 3rd face opposite a beveled edge, with no vmesh */
- i = v->index;
- e = v->ebev;
- for (k = 1; k < e->seg; k++) {
- bmv = mesh_vert(vm, i, 0, k)->v;
- BLI_array_append(vv, bmv);
- BLI_array_append(ee, bme);
- /* may want to merge UVs of these later */
- if (!e->is_seam)
- BLI_array_append(vv_fix, bmv);
+ if (go_ccw) {
+ if (vm->seg > 1) {
+ if (vm->mesh_kind == M_ADJ || bp->vertex_only || corner3special) {
+ i = v->index;
+ for (k = 1; k < vm->seg; k++) {
+ bmv = mesh_vert(vm, i, 0, k)->v;
+ BLI_array_append(vv, bmv);
+ BLI_array_append(ee, bme); /* TODO: maybe better edge here */
+ if (corner3special && v->ebev && !v->ebev->is_seam)
+ BLI_array_append(vv_fix, bmv);
+ }
+ }
}
+ v = v->next;
}
- else if ((vm->mesh_kind == M_ADJ || bp->vertex_only) && vm->seg > 1 && !e->is_bev && !eprev->is_bev) {
- BLI_assert(v->prev == vend);
- i = vend->index;
- for (k = vm->seg - 1; k > 0; k--) {
- bmv = mesh_vert(vm, i, 0, k)->v;
- BLI_array_append(vv, bmv);
- BLI_array_append(ee, bme);
+ else {
+ /* going cw */
+ if (vm->seg > 1) {
+ if (vm->mesh_kind == M_ADJ || bp->vertex_only ||
+ (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev))
+ {
+ i = v->prev->index;
+ for (k = vm->seg - 1; k > 0; k--) {
+ bmv = mesh_vert(vm, i, 0, k)->v;
+ BLI_array_append(vv, bmv);
+ BLI_array_append(ee, bme);
+ if (corner3special && v->ebev && !v->ebev->is_seam)
+ BLI_array_append(vv_fix, bmv);
+ }
+ }
}
+ v = v->prev;
}
- v = v->prev;
BLI_array_append(vv, v->nv.v);
BLI_array_append(ee, bme);
}
-
do_rebuild = true;
}
else {
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 36ab85b9b5b..4f5cf83f5ca 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -67,12 +67,19 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce,
std::list<Object *>& child_objects)
{
// write bone nodes
+
+ bArmature * armature = (bArmature *)ob_arm->data;
+ ED_armature_to_edit(armature);
+
bArmature *arm = (bArmature *)ob_arm->data;
for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
// start from root bones
if (!bone->parent)
add_bone_node(bone, ob_arm, sce, se, child_objects);
}
+
+ ED_armature_from_edit(armature);
+ ED_armature_edit_free(armature);
}
void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
@@ -167,12 +174,30 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
node.setNodeName(node_name);
node.setNodeSid(node_sid);
-#if 0
- if (BLI_listbase_is_empty(&bone->childbase) || BLI_listbase_count_ex(&bone->childbase, 2) == 2) {
- add_blender_leaf_bone( bone, ob_arm, node);
+ if (this->export_settings->use_blender_profile)
+ {
+ if (bone->parent) {
+ if (bone->flag & BONE_CONNECTED) {
+ node.addExtraTechniqueParameter("blender", "connect", true);
+ }
+ }
+ std::string layers = BoneExtended::get_bone_layers(bone->layer);
+ node.addExtraTechniqueParameter("blender", "layer", layers);
+
+ bArmature *armature = (bArmature *)ob_arm->data;
+ EditBone *ebone = bc_get_edit_bone(armature, bone->name);
+ if (ebone && ebone->roll != 0)
+ {
+ node.addExtraTechniqueParameter("blender", "roll", ebone->roll);
+ }
+ if (bc_is_leaf_bone(bone))
+ {
+ node.addExtraTechniqueParameter("blender", "tip_x", bone->arm_tail[0] - bone->arm_head[0]);
+ node.addExtraTechniqueParameter("blender", "tip_y", bone->arm_tail[1] - bone->arm_head[1]);
+ node.addExtraTechniqueParameter("blender", "tip_z", bone->arm_tail[2] - bone->arm_head[2]);
+ }
}
- else {
-#endif
+
node.start();
add_bone_transform(ob_arm, bone, node);
@@ -227,25 +252,6 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
}
}
-//#if 1
-void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADASW::Node& node)
-{
- node.start();
-
- add_bone_transform(ob_arm, bone, node);
-
- node.addExtraTechniqueParameter("blender", "tip_x", bone->tail[0]);
- node.addExtraTechniqueParameter("blender", "tip_y", bone->tail[1]);
- node.addExtraTechniqueParameter("blender", "tip_z", bone->tail[2]);
-
- /*for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
- add_bone_node(child, ob_arm, sce, se, child_objects);
- }*/
- node.end();
-
-}
-//#endif
-
void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node)
{
//bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h
index 931cc5d2988..883a6aca847 100644
--- a/source/blender/collada/ArmatureExporter.h
+++ b/source/blender/collada/ArmatureExporter.h
@@ -92,8 +92,6 @@ private:
void add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node);
- void add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADASW::Node& node);
-
std::string get_controller_id(Object *ob_arm, Object *ob);
void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone);
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index fd08e1ebfab..fca9b9ffa55 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -50,19 +50,6 @@ static const char *bc_get_joint_name(T *node)
return id.size() ? id.c_str() : node->getOriginalId().c_str();
}
-static EditBone *get_edit_bone(bArmature * armature, char *name) {
- EditBone *eBone;
-
- for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
- if (STREQ(name, eBone->name))
- return eBone;
- }
-
- return NULL;
-
-}
-
-
ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, const ImportSettings *import_settings) :
import_settings(import_settings),
@@ -110,7 +97,7 @@ JointData *ArmatureImporter::get_joint_data(COLLADAFW::Node *node);
#endif
int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
- float parent_mat[4][4], bArmature *arm)
+ float parent_mat[4][4], bArmature *arm, std::vector<std::string> &layer_labels)
{
float mat[4][4];
float joint_inv_bind_mat[4][4];
@@ -157,22 +144,41 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
if (parent) bone->parent = parent;
float loc[3], size[3], rot[3][3];
- float angle;
- float vec[3] = {0.0f, 0.5f, 0.0f};
- mat4_to_loc_rot_size(loc, rot, size, mat);
- //copy_m3_m4(bonemat,mat);
- mat3_to_vec_roll(rot, vec, &angle);
-
- bone->roll = angle;
- // set head
- copy_v3_v3(bone->head, mat[3]);
- // set tail, don't set it to head because 0-length bones are not allowed
- add_v3_v3v3(bone->tail, bone->head, vec);
+ BoneExtended &be = add_bone_extended(bone, node, layer_labels);
+ int layer = be.get_bone_layers();
+ if (layer) bone->layer = layer;
+ arm->layer |= layer; // ensure that all populated bone layers are visible after import
+
+ float *tail = be.get_tail();
+ int use_connect = be.get_use_connect();
+
+ switch (use_connect) {
+ case 1: bone->flag |= BONE_CONNECTED;
+ break;
+ case 0: bone->flag &= ~BONE_CONNECTED;
+ case -1: break; // not defined
+ }
+
+ if (be.has_roll()) {
+ bone->roll = be.get_roll();
+ }
+ else {
+ float angle;
+ mat4_to_loc_rot_size(loc, rot, size, mat);
+ mat3_to_vec_roll(rot, NULL, &angle);
+ }
+
+ copy_v3_v3(bone->head, mat[3]);
+ add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero
/* find smallest bone length in armature (used later for leaf bone length) */
if (parent) {
+ if (use_connect == 1) {
+ copy_v3_v3(parent->tail, bone->head);
+ }
+
/* guess reasonable leaf bone length */
float length = len_v3v3(parent->head, bone->head);
if ((length < leaf_bone_length || totbone == 0) && length > MINIMUM_BONE_LENGTH) {
@@ -182,11 +188,8 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
COLLADAFW::NodePointerArray& children = node->getChildNodes();
- BoneExtended &be = add_bone_extended(bone, node);
- be.set_leaf_bone(true);
-
for (unsigned int i = 0; i < children.getCount(); i++) {
- int cl = create_bone(skin, children[i], bone, children.getCount(), mat, arm);
+ int cl = create_bone(skin, children[i], bone, children.getCount(), mat, arm, layer_labels);
if (cl > chain_length)
chain_length = cl;
}
@@ -209,22 +212,23 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
**/
void ArmatureImporter::fix_leaf_bones(bArmature *armature, Bone *bone)
{
- /* armature has no bones */
if (bone == NULL)
return;
- BoneExtended *be = extended_bones[bone->name];
- if (be != NULL && be->is_leaf_bone() ) {
- /* Collada only knows Joints, Here we guess a reasonable leaf bone length */
- float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0 : leaf_bone_length;
+ if (bc_is_leaf_bone(bone)) {
+
+ BoneExtended *be = extended_bones[bone->name];
+ if (be == NULL || !be->has_tail()) {
- EditBone *ebone = get_edit_bone(armature, bone->name);
- float vec[3];
+ /* Collada only knows Joints, Here we guess a reasonable leaf bone length */
+ float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0 : leaf_bone_length;
+
+ EditBone *ebone = bc_get_edit_bone(armature, bone->name);
+ float vec[3];
- if (this->import_settings->fix_orientation) {
if (ebone->parent != NULL) {
EditBone *parent = ebone->parent;
- sub_v3_v3v3(vec, ebone->head, parent->tail);
+ sub_v3_v3v3(vec, ebone->head, parent->head);
if (len_squared_v3(vec) < MINIMUM_BONE_LENGTH)
{
sub_v3_v3v3(vec, parent->tail, parent->head);
@@ -234,19 +238,31 @@ void ArmatureImporter::fix_leaf_bones(bArmature *armature, Bone *bone)
vec[2] = 0.1f;
sub_v3_v3v3(vec, ebone->tail, ebone->head);
}
- }
- else {
- sub_v3_v3v3(vec, ebone->tail, ebone->head);
- }
- normalize_v3_v3(vec, vec);
- mul_v3_fl(vec, leaf_length);
- add_v3_v3v3(ebone->tail, ebone->head, vec);
+ normalize_v3_v3(vec, vec);
+ mul_v3_fl(vec, leaf_length);
+ add_v3_v3v3(ebone->tail, ebone->head, vec);
+ }
}
for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
fix_leaf_bones(armature, child);
}
+}
+
+void ArmatureImporter::fix_parent_connect(bArmature *armature, Bone *bone)
+{
+ /* armature has no bones */
+ if (bone == NULL)
+ return;
+
+ if (bone->parent && bone->flag & BONE_CONNECTED) {
+ copy_v3_v3(bone->parent->tail, bone->head);
+ }
+
+ for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+ fix_parent_connect(armature, child);
+ }
}
@@ -281,8 +297,8 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
BoneExtended *pbe = extended_bones[parentbone->name];
if (dominant_child != NULL) {
/* Found a valid chain. Now connect current bone with that chain.*/
- EditBone *pebone = get_edit_bone(armature, parentbone->name);
- EditBone *cebone = get_edit_bone(armature, dominant_child->get_name());
+ EditBone *pebone = bc_get_edit_bone(armature, parentbone->name);
+ EditBone *cebone = bc_get_edit_bone(armature, dominant_child->get_name());
if (pebone && !(cebone->flag & BONE_CONNECTED)) {
float vec[3];
@@ -421,6 +437,7 @@ ArmatureJoints& ArmatureImporter::get_armature_joints(Object *ob_arm)
void ArmatureImporter::create_armature_bones( )
{
std::vector<COLLADAFW::Node *>::iterator ri;
+ std::vector<std::string> layer_labels;
leaf_bone_length = FLT_MAX;
//if there is an armature created for root_joint next root_joint
@@ -445,8 +462,9 @@ void ArmatureImporter::create_armature_bones( )
clear_extended_boneset();
ED_armature_to_edit(armature);
+ armature->layer = 0; // layer is set according to imported bone set in create_bone()
- create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, armature);
+ create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, armature, layer_labels);
/* exit armature edit mode to populate the Armature object */
ED_armature_from_edit(armature);
@@ -455,14 +473,23 @@ void ArmatureImporter::create_armature_bones( )
/* and step back to edit mode to fix the leaf nodes */
ED_armature_to_edit(armature);
- connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
- fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
+ if (this->import_settings->fix_orientation || this->import_settings->find_chains) {
+
+ if (this->import_settings->find_chains)
+ connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
- // exit armature edit mode
- unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm;
+ if (this->import_settings->fix_orientation)
+ fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
+
+ // exit armature edit mode
+ unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm;
+ }
+
+ fix_parent_connect(armature, (Bone *)armature->bonebase.first);
ED_armature_from_edit(armature);
ED_armature_edit_free(armature);
+
DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
}
}
@@ -513,6 +540,7 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
SkinInfo *a = &skin;
Object *shared = NULL;
std::vector<COLLADAFW::Node *> skin_root_joints;
+ std::vector<std::string> layer_labels;
std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it;
for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
@@ -578,7 +606,7 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
// since root_joints may contain joints for multiple controllers, we need to filter
if (skin.uses_joint_or_descendant(*ri)) {
- create_bone(&skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, armature);
+ create_bone(&skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, armature, layer_labels);
if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent())
skin.set_parent(joint_parent_map[(*ri)->getUniqueId()]);
@@ -594,8 +622,8 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
if (armature->bonebase.first) {
/* Do this only if Armature has bones */
- connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
- fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
+ //connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
+ //fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
}
// exit armature edit mode
ED_armature_from_edit(armature);
@@ -894,70 +922,44 @@ bool ArmatureImporter::get_joint_bind_mat(float m[4][4], COLLADAFW::Node *joint)
return found;
}
-
-/**
- * BoneExtended is a helper class needed for the Bone chain finder
- * See ArmatureImporter::fix_leaf_bones()
- * and ArmatureImporter::connect_bone_chains()
- **/
-
-BoneExtended::BoneExtended(EditBone *aBone)
-{
- this->set_name(aBone->name);
- this->chain_length = 0;
- this->is_leaf = false;
-}
-
-char *BoneExtended::get_name()
-{
- return name;
-}
-
-void BoneExtended::set_name(char *aName)
-{
- BLI_strncpy(name, aName, MAXBONENAME);
-}
-
-int BoneExtended::get_chain_length()
-{
- return chain_length;
-}
-
-void BoneExtended::set_chain_length(const int aLength)
-{
- chain_length = aLength;
-}
-
-
-void BoneExtended::set_leaf_bone(bool state)
-{
- is_leaf = state;
-}
-
-bool BoneExtended::is_leaf_bone()
-{
- return is_leaf;
-}
-
-BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node)
+BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node, std::vector<std::string> &layer_labels)
{
+ BoneExtended *be = new BoneExtended(bone);
+ extended_bones[bone->name] = be;
TagsMap::iterator etit;
ExtraTags *et = 0;
etit = uid_tags_map.find(node->getUniqueId().toAscii());
if (etit != uid_tags_map.end()) {
- float x, y, z;
+
+ float tail[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
+ float roll = 0;
+ int use_connect = -1;
+ std::string layers;
et = etit->second;
- et->setData("tip_x", &x);
- et->setData("tip_y", &y);
- et->setData("tip_z", &z);
- float vec[3] = { x, y, z };
- copy_v3_v3(bone->tail, bone->head);
- add_v3_v3v3(bone->tail, bone->head, vec);
+
+ bool has_tail = false;
+ has_tail |= et->setData("tip_x", &tail[0]);
+ has_tail |= et->setData("tip_y", &tail[1]);
+ has_tail |= et->setData("tip_z", &tail[2]);
+
+ bool has_connect = et->setData("connect", &use_connect);
+ bool has_roll = et->setData("roll", &roll);
+
+ layers = et->setData("layer", layers);
+
+ if (has_tail && !has_connect)
+ {
+ use_connect = 0; // got a bone tail definition but no connect info -> bone is not connected
+ }
+
+ be->set_bone_layers(layers, layer_labels);
+ if (has_tail) be->set_tail(tail);
+ if (has_roll) be->set_roll(roll);
+ be->set_use_connect(use_connect);
}
+ be->set_leaf_bone(true);
- BoneExtended *be = new BoneExtended(bone);
- extended_bones[bone->name] = be;
return *be;
}
diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h
index 732fda80ff1..f38bd1a6c66 100644
--- a/source/blender/collada/ArmatureImporter.h
+++ b/source/blender/collada/ArmatureImporter.h
@@ -59,25 +59,6 @@ extern "C" {
#define UNLIMITED_CHAIN_MAX INT_MAX
#define MINIMUM_BONE_LENGTH 0.000001f
-class BoneExtended {
-
-private:
- char name[MAXBONENAME];
- int chain_length;
- bool is_leaf;
-
-public:
-
- BoneExtended(EditBone *aBone);
- char *get_name();
- int get_chain_length();
-
- void set_name(char *aName);
- void set_chain_length(const int aLength);
- void set_leaf_bone(bool state);
- bool is_leaf_bone();
-};
-
class ArmatureImporter : private TransformReader
{
private:
@@ -125,12 +106,13 @@ private:
#endif
int create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
- float parent_mat[4][4], bArmature *arm);
+ float parent_mat[4][4], bArmature *arm, std::vector<std::string> &layer_labels);
- BoneExtended &add_bone_extended(EditBone *bone, COLLADAFW::Node * node);
+ BoneExtended &add_bone_extended(EditBone *bone, COLLADAFW::Node * node, std::vector<std::string> &layer_labels);
void clear_extended_boneset();
void fix_leaf_bones(bArmature *armature, Bone *bone);
+ void fix_parent_connect(bArmature *armature, Bone *bone);
void connect_bone_chains(bArmature *armature, Bone *bone, const int max_chain_length);
void set_pose( Object *ob_arm, COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4]);
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index 3dc7e74379e..9451cac9dae 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -48,6 +48,7 @@ public:
bool triangulate;
bool use_object_instantiation;
+ bool use_blender_profile;
bool sort_by_name;
BC_export_transformation_type export_transformation_type;
bool open_sim;
diff --git a/source/blender/collada/ExtraTags.cpp b/source/blender/collada/ExtraTags.cpp
index 6af61432fda..ea225d8a4ae 100644
--- a/source/blender/collada/ExtraTags.cpp
+++ b/source/blender/collada/ExtraTags.cpp
@@ -85,32 +85,45 @@ std::string ExtraTags::asString(std::string tag, bool *ok)
}
-void ExtraTags::setData(std::string tag, short *data)
+bool ExtraTags::setData(std::string tag, short *data)
{
bool ok = false;
int tmp = asInt(tag, &ok);
if (ok)
*data = (short)tmp;
+ return ok;
}
-void ExtraTags::setData(std::string tag, int *data)
+
+bool ExtraTags::setData(std::string tag, int *data)
{
bool ok = false;
int tmp = asInt(tag, &ok);
if (ok)
*data = tmp;
+ return ok;
}
-void ExtraTags::setData(std::string tag, float *data)
+
+bool ExtraTags::setData(std::string tag, float *data)
{
bool ok = false;
float tmp = asFloat(tag, &ok);
if (ok)
*data = tmp;
+ return ok;
}
-void ExtraTags::setData(std::string tag, char *data)
+
+bool ExtraTags::setData(std::string tag, char *data)
{
bool ok = false;
int tmp = asInt(tag, &ok);
if (ok)
*data = (char)tmp;
+ return ok;
+}
+
+std::string ExtraTags::setData(std::string tag, std::string &data)
+{
+ bool ok = false;
+ std::string tmp = asString(tag, &ok);
+ return (ok) ? tmp : data;
}
-
diff --git a/source/blender/collada/ExtraTags.h b/source/blender/collada/ExtraTags.h
index 03a311a7e86..ad272dcba65 100644
--- a/source/blender/collada/ExtraTags.h
+++ b/source/blender/collada/ExtraTags.h
@@ -43,17 +43,18 @@ public:
bool addTag(std::string tag, std::string data);
/** Set given short pointer to value of tag, if it exists. */
- void setData(std::string tag, short *data);
+ bool setData(std::string tag, short *data);
/** Set given int pointer to value of tag, if it exists. */
- void setData(std::string tag, int *data);
+ bool setData(std::string tag, int *data);
/** Set given float pointer to value of tag, if it exists. */
- void setData(std::string tag, float *data);
+ bool setData(std::string tag, float *data);
/** Set given char pointer to value of tag, if it exists. */
- void setData(std::string tag, char *data);
-
+ bool setData(std::string tag, char *data);
+ std::string setData(std::string tag, std::string &data);
+
/** Return true if the extra tags is for specified profile. */
bool isProfile(std::string profile);
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index a884268fd5e..76f24545248 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -259,7 +259,8 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) // checks if mesh has su
COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
const std::string &name = bc_get_dae_name(mesh);
-
+ int hole_count = 0;
+
for (unsigned i = 0; i < prim_arr.getCount(); i++) {
COLLADAFW::MeshPrimitive *mp = prim_arr[i];
@@ -275,13 +276,21 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) // checks if mesh has su
for (unsigned int j = 0; j < vca.getCount(); j++) {
int count = vca[j];
- if (count < 3) {
- fprintf(stderr, "Primitive %s in %s has at least one face with vertex count < 3\n",
+ if (abs(count) < 3) {
+ fprintf(stderr, "ERROR: Primitive %s in %s has at least one face with vertex count < 3\n",
type_str, name.c_str());
return false;
}
+ if (count < 0)
+ {
+ hole_count ++;
+ }
+ }
+
+ if (hole_count > 0)
+ {
+ fprintf(stderr, "WARNING: Primitive %s in %s: %d holes not imported (unsupported)\n", type_str, name.c_str(), hole_count);
}
-
}
else if (type == COLLADAFW::MeshPrimitive::LINES) {
@@ -289,13 +298,13 @@ bool MeshImporter::is_nice_mesh(COLLADAFW::Mesh *mesh) // checks if mesh has su
}
else if (type != COLLADAFW::MeshPrimitive::TRIANGLES && type != COLLADAFW::MeshPrimitive::TRIANGLE_FANS) {
- fprintf(stderr, "Primitive type %s is not supported.\n", type_str);
+ fprintf(stderr, "ERROR: Primitive type %s is not supported.\n", type_str);
return false;
}
}
if (mesh->getPositions().empty()) {
- fprintf(stderr, "Mesh %s has no vertices.\n", name.c_str());
+ fprintf(stderr, "ERROR: Mesh %s has no vertices.\n", name.c_str());
return false;
}
@@ -409,11 +418,18 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
size_t prim_poly_count = mpvc->getFaceCount();
size_t prim_loop_count = 0;
- for (int index=0; index < prim_poly_count; index++) {
- prim_loop_count += get_vertex_count(mpvc, index);
+ for (int index=0; index < prim_poly_count; index++)
+ {
+ int vcount = get_vertex_count(mpvc, index);
+ if (vcount > 0) {
+ prim_loop_count += vcount;
+ total_poly_count++;
+ }
+ else {
+ // TODO: this is a hole and not another polygon!
+ }
}
- total_poly_count += prim_poly_count;
total_loop_count += prim_loop_count;
break;
@@ -683,9 +699,12 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
COLLADAFW::IndexListArray& index_list_array_vcolor = mp->getColorIndicesArray();
for (unsigned int j = 0; j < prim_totpoly; j++) {
-
+
// Vertices in polygon:
int vcount = get_vertex_count(mpvc, j);
+ if (vcount < 0) {
+ continue; // TODO: add support for holes
+ }
set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index b64b10e0833..e1b8a2dd30a 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -81,8 +81,9 @@ int collada_export(Scene *sce,
int use_texture_copies,
int triangulate,
- int use_object_instantiation,
- int sort_by_name,
+ int use_object_instantiation,
+ int use_blender_profile,
+ int sort_by_name,
BC_export_transformation_type export_transformation_type,
int open_sim)
{
@@ -105,6 +106,7 @@ int collada_export(Scene *sce,
export_settings.triangulate = triangulate != 0;
export_settings.use_object_instantiation = use_object_instantiation != 0;
+ export_settings.use_blender_profile = use_blender_profile != 0;
export_settings.sort_by_name = sort_by_name != 0;
export_settings.export_transformation_type = export_transformation_type;
export_settings.open_sim = open_sim != 0;
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index 6819a62fdf0..db8ea884222 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -78,6 +78,7 @@ int collada_export(struct Scene *sce,
int triangulate,
int use_object_instantiation,
+ int use_blender_profile,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
int open_sim);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index f8feed8145c..f0984fbc127 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -54,6 +54,8 @@ extern "C" {
#include "BKE_scene.h"
#include "BKE_DerivedMesh.h"
+#include "ED_armature.h"
+
#include "WM_api.h" // XXX hrm, see if we can do without this
#include "WM_types.h"
@@ -366,3 +368,212 @@ void bc_triangulate_mesh(Mesh *me)
BM_mesh_bm_to_me(bm, me, &bm_to_me_params);
BM_mesh_free(bm);
}
+
+/*
+* A bone is a leaf when it has no children or all children are not connected.
+*/
+bool bc_is_leaf_bone(Bone *bone)
+{
+ for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+ if (child->flag & BONE_CONNECTED)
+ return false;
+ }
+ return true;
+}
+
+EditBone *bc_get_edit_bone(bArmature * armature, char *name) {
+ EditBone *eBone;
+
+ for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) {
+ if (STREQ(name, eBone->name))
+ return eBone;
+ }
+
+ return NULL;
+
+}
+int bc_set_layer(int bitfield, int layer)
+{
+ return bc_set_layer(bitfield, layer, true); /* enable */
+}
+
+int bc_set_layer(int bitfield, int layer, bool enable)
+{
+ int bit = 1u << layer;
+
+ if (enable)
+ bitfield |= bit;
+ else
+ bitfield &= ~bit;
+
+ return bitfield;
+}
+
+/**
+* BoneExtended is a helper class needed for the Bone chain finder
+* See ArmatureImporter::fix_leaf_bones()
+* and ArmatureImporter::connect_bone_chains()
+**/
+
+BoneExtended::BoneExtended(EditBone *aBone)
+{
+ this->set_name(aBone->name);
+ this->chain_length = 0;
+ this->is_leaf = false;
+ this->tail[0] = 0.0f;
+ this->tail[1] = 0.5f;
+ this->tail[2] = 0.0f;
+ this->use_connect = -1;
+ this->roll = 0;
+ this->bone_layers = 0;
+
+ this->has_custom_tail = false;
+ this->has_custom_roll = false;
+}
+
+char *BoneExtended::get_name()
+{
+ return name;
+}
+
+void BoneExtended::set_name(char *aName)
+{
+ BLI_strncpy(name, aName, MAXBONENAME);
+}
+
+int BoneExtended::get_chain_length()
+{
+ return chain_length;
+}
+
+void BoneExtended::set_chain_length(const int aLength)
+{
+ chain_length = aLength;
+}
+
+void BoneExtended::set_leaf_bone(bool state)
+{
+ is_leaf = state;
+}
+
+bool BoneExtended::is_leaf_bone()
+{
+ return is_leaf;
+}
+
+void BoneExtended::set_roll(float roll)
+{
+ this->roll = roll;
+ this->has_custom_roll = true;
+}
+
+bool BoneExtended::has_roll()
+{
+ return this->has_custom_roll;
+}
+
+float BoneExtended::get_roll()
+{
+ return this->roll;
+}
+
+void BoneExtended::set_tail(float vec[])
+{
+ this->tail[0] = vec[0];
+ this->tail[1] = vec[1];
+ this->tail[2] = vec[2];
+ this->has_custom_tail = true;
+}
+
+bool BoneExtended::has_tail()
+{
+ return this->has_custom_tail;
+}
+
+float *BoneExtended::get_tail()
+{
+ return this->tail;
+}
+
+inline bool isInteger(const std::string & s)
+{
+ if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;
+
+ char * p;
+ strtol(s.c_str(), &p, 10);
+
+ return (*p == 0);
+}
+
+void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::string> &layer_labels)
+{
+ std::stringstream ss(layerString);
+ std::string layer;
+ int pos;
+
+ while (ss >> layer) {
+
+ /* Blender uses numbers to specify layers*/
+ if (isInteger(layer))
+ {
+ pos = atoi(layer.c_str());
+ if (pos >= 0 && pos < 32) {
+ this->bone_layers = bc_set_layer(this->bone_layers, pos);
+ continue;
+ }
+ }
+
+ /* layer uses labels (not supported by blender). Map to layer numbers:*/
+ pos = find(layer_labels.begin(), layer_labels.end(), layer) - layer_labels.begin();
+ if (pos >= layer_labels.size()) {
+ layer_labels.push_back(layer); /* remember layer number for future usage*/
+ }
+
+ if (pos > 31)
+ {
+ fprintf(stderr, "Too many layers in Import. Layer %s mapped to Blender layer 31\n", layer.c_str());
+ pos = 31;
+ }
+
+ /* If numeric layers and labeled layers are used in parallel (unlikely),
+ we get a potential mixup. Just leave as is for now.
+ */
+ this->bone_layers = bc_set_layer(this->bone_layers, pos);
+
+ }
+}
+
+std::string BoneExtended::get_bone_layers(int bitfield)
+{
+ std::string result = "";
+ std::string sep = "";
+ int bit = 1u;
+
+ std::ostringstream ss;
+ for (int i = 0; i < 32; i++)
+ {
+ if (bit & bitfield)
+ {
+ ss << sep << i;
+ sep = " ";
+ }
+ bit = bit << 1;
+ }
+ return ss.str();
+}
+
+int BoneExtended::get_bone_layers()
+{
+ return (bone_layers == 0) ? 1 : bone_layers; // ensure that the bone is in at least one bone layer!
+}
+
+
+void BoneExtended::set_use_connect(int use_connect)
+{
+ this->use_connect = use_connect;
+}
+
+int BoneExtended::get_use_connect()
+{
+ return this->use_connect;
+}
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index 4bc2f55cf33..74f8dca1492 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -34,6 +34,7 @@
#include <vector>
#include <map>
+#include <algorithm>
extern "C" {
#include "DNA_object_types.h"
@@ -46,6 +47,7 @@ extern "C" {
#include "BLI_linklist.h"
#include "BLI_utildefines.h"
+#include "BLI_string.h"
#include "BKE_context.h"
#include "BKE_object.h"
@@ -87,7 +89,10 @@ extern void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_sce
extern void bc_match_scale(std::vector<Object *> *objects_done, UnitConverter &unit_converter, bool scale_to_scene);
extern void bc_triangulate_mesh(Mesh *me);
-
+extern bool bc_is_leaf_bone(Bone *bone);
+extern EditBone *bc_get_edit_bone(bArmature * armature, char *name);
+extern int bc_set_layer(int bitfield, int layer, bool enable);
+extern int bc_set_layer(int bitfield, int layer);
class BCPolygonNormalsIndices
{
@@ -105,4 +110,48 @@ class BCPolygonNormalsIndices
};
+class BoneExtended {
+
+private:
+ char name[MAXBONENAME];
+ int chain_length;
+ bool is_leaf;
+ float tail[3];
+ float roll;
+
+ int bone_layers;
+ bool use_connect;
+ bool has_custom_tail;
+ bool has_custom_roll;
+
+public:
+
+ BoneExtended(EditBone *aBone);
+
+ void set_name(char *aName);
+ char *get_name();
+
+ void set_chain_length(const int aLength);
+ int get_chain_length();
+
+ void set_leaf_bone(bool state);
+ bool is_leaf_bone();
+
+ void set_bone_layers(std::string layers, std::vector<std::string> &layer_labels);
+ int get_bone_layers();
+ static std::string get_bone_layers(int bitfield);
+
+ void set_roll(float roll);
+ bool has_roll();
+ float get_roll();
+
+ void set_tail(float *vec);
+ float *get_tail();
+ bool has_tail();
+
+ void set_use_connect(int use_connect);
+ int get_use_connect();
+};
+
+
#endif
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index 2b4df85f29c..fd2a521bec5 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -25,8 +25,6 @@
set(INC
.
- intern
- util
../blenkernel
../blenlib
../bmesh
@@ -42,45 +40,50 @@ set(INC_SYS
)
set(SRC
+ intern/builder/deg_builder.cc
+ intern/builder/deg_builder_cycle.cc
+ intern/builder/deg_builder_nodes.cc
+ intern/builder/deg_builder_pchanmap.cc
+ intern/builder/deg_builder_relations.cc
+ intern/builder/deg_builder_transitive.cc
+ intern/debug/deg_debug_graphviz.cc
+ intern/eval/deg_eval.cc
+ intern/eval/deg_eval_debug.cc
+ intern/eval/deg_eval_flush.cc
+ intern/nodes/deg_node.cc
+ intern/nodes/deg_node_component.cc
+ intern/nodes/deg_node_operation.cc
intern/depsgraph.cc
- intern/depsnode.cc
- intern/depsnode_component.cc
- intern/depsnode_operation.cc
intern/depsgraph_build.cc
- intern/depsgraph_build_nodes.cc
- intern/depsgraph_build_relations.cc
intern/depsgraph_debug.cc
intern/depsgraph_eval.cc
intern/depsgraph_query.cc
- intern/depsgraph_queue.cc
intern/depsgraph_tag.cc
intern/depsgraph_type_defines.cc
- util/depsgraph_util_cycle.cc
- util/depsgraph_util_pchanmap.cc
- util/depsgraph_util_transitive.cc
DEG_depsgraph.h
DEG_depsgraph_build.h
DEG_depsgraph_debug.h
DEG_depsgraph_query.h
+
+ intern/builder/deg_builder.h
+ intern/builder/deg_builder_cycle.h
+ intern/builder/deg_builder_nodes.h
+ intern/builder/deg_builder_pchanmap.h
+ intern/builder/deg_builder_relations.h
+ intern/builder/deg_builder_transitive.h
+ intern/eval/deg_eval.h
+ intern/eval/deg_eval_debug.h
+ intern/eval/deg_eval_flush.h
+ intern/nodes/deg_node.h
+ intern/nodes/deg_node_component.h
+ intern/nodes/deg_node_operation.h
intern/depsgraph.h
- intern/depsnode.h
- intern/depsnode_component.h
- intern/depsnode_operation.h
- intern/depsnode_opcodes.h
- intern/depsgraph_build.h
- intern/depsgraph_debug.h
intern/depsgraph_intern.h
- intern/depsgraph_queue.h
intern/depsgraph_types.h
- util/depsgraph_util_cycle.h
- util/depsgraph_util_function.h
- util/depsgraph_util_hash.h
- util/depsgraph_util_map.h
- util/depsgraph_util_pchanmap.h
- util/depsgraph_util_set.h
- util/depsgraph_util_transitive.h
+ util/deg_util_function.h
+ util/deg_util_hash.h
)
if(WITH_CXX11)
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index f37ba71ab65..d1de83ec8a9 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -131,9 +131,6 @@ void DEG_ids_clear_recalc(struct Main *bmain);
/* Update Flushing ------------------------------- */
-/* Flush updates */
-void DEG_graph_flush_updates(struct Main *bmain, Depsgraph *graph);
-
/* Flush updates for all IDs */
void DEG_ids_flush_tagged(struct Main *bmain);
@@ -144,11 +141,6 @@ void DEG_ids_check_recalc(struct Main *bmain,
struct Scene *scene,
bool time);
-/* Clear all update tags
- * - For aborted updates, or after successful evaluation
- */
-void DEG_graph_clear_tags(Depsgraph *graph);
-
/* ************************************************ */
/* Evaluation Engine API */
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index f680c47247a..49b648c7dae 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -43,9 +43,6 @@ struct Depsgraph;
struct Main;
struct Scene;
-struct PointerRNA;
-struct PropertyRNA;
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/source/blender/depsgraph/DEG_depsgraph_debug.h b/source/blender/depsgraph/DEG_depsgraph_debug.h
index 374fad63c34..0d19b8e1e97 100644
--- a/source/blender/depsgraph/DEG_depsgraph_debug.h
+++ b/source/blender/depsgraph/DEG_depsgraph_debug.h
@@ -39,13 +39,10 @@
extern "C" {
#endif
-struct DepsgraphSettings;
struct GHash;
struct ID;
struct Depsgraph;
-struct DepsNode;
-struct DepsRelation;
/* ************************************************ */
/* Statistics */
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
index 60d673d4c5b..ccd204a2083 100644
--- a/source/blender/depsgraph/DEG_depsgraph_query.h
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -19,7 +19,7 @@
* All rights reserved.
*
* Original Author: Joshua Leung
- * Contributor(s): None Yet
+ * Contributor(s): Sergey Sharybin
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -33,155 +33,14 @@
#ifndef __DEG_DEPSGRAPH_QUERY_H__
#define __DEG_DEPSGRAPH_QUERY_H__
-struct ListBase;
struct ID;
struct Depsgraph;
-struct DepsNode;
-struct DepsRelation;
#ifdef __cplusplus
extern "C" {
#endif
-/* ************************************************ */
-/* Type Defines */
-
-/* FilterPredicate Callback
- *
- * Defines a callback function which can be supplied to check whether a
- * node is relevant or not.
- *
- * < graph: Depsgraph that we're traversing
- * < node: The node to check
- * < userdata: FilterPredicate state data (as needed)
- * > returns: True if node is relevant
- */
-typedef bool (*DEG_FilterPredicate)(const struct Depsgraph *graph, const struct DepsNode *node, void *userdata);
-
-
-/* Node Operation
- *
- * Performs some action on the given node, provided that the node was
- * deemed to be relevant to operate on.
- *
- * < graph: Depsgraph that we're traversing
- * < node: The node to perform operation on/with
- * < userdata: Node Operation's state data (as needed)
- * > returns: True if traversal should be aborted at this point
- */
-typedef bool (*DEG_NodeOperation)(const struct Depsgraph *graph, struct DepsNode *node, void *userdata);
-
-/* ************************************************ */
-/* Low-Level Filtering API */
-
-/* Create a filtered copy of the given graph which contains only the
- * nodes which fulfill the criteria specified using the FilterPredicate
- * passed in.
- *
- * < graph: The graph to be copied and filtered
- * < filter: FilterPredicate used to check which nodes should be included
- * (If null, full graph is copied as-is)
- * < userdata: State data for filter (as necessary)
- *
- * > returns: a full copy of all the relevant nodes - the matching subgraph
- */
-// XXX: is there any need for extra settings/options for how the filtering goes?
-Depsgraph *DEG_graph_filter(const struct Depsgraph *graph, DEG_FilterPredicate *filter, void *userdata);
-
-
-/* Traverse nodes in graph which are deemed relevant,
- * performing the provided operation on the nodes.
- *
- * < graph: The graph to perform operations on
- * < filter: FilterPredicate used to check which nodes should be included
- * (If null, all nodes are considered valid targets)
- * < filter_data: Custom state data for FilterPredicate
- * (Note: This can be the same as op_data, where appropriate)
- * < op: NodeOperation to perform on each node
- * (If null, no graph traversal is performed for efficiency)
- * < op_data: Custom state data for NodeOperation
- * (Note: This can be the same as filter_data, where appropriate)
- */
-void DEG_graph_traverse(const struct Depsgraph *graph,
- DEG_FilterPredicate *filter, void *filter_data,
- DEG_NodeOperation *op, void *op_data);
-
-/* ************************************************ */
-/* Node-Based Operations */
-// XXX: do we want to be able to attach conditional requirements here?
-
-/* Find an (outer) node matching given conditions
- * ! Assumes that there will only be one such node, or that only the first one matters
- *
- * < graph: a dependency graph which may or may not contain a node matching these requirements
- * < query: query conditions for the criteria that the node must satisfy
- */
-//DepsNode *DEG_node_find(const Depsgraph *graph, DEG_QueryConditions *query);
-
-/* Topology Queries (Direct) ---------------------- */
-
-/* Get list of nodes which directly depend on given node
- *
- * > result: list to write results to
- * < node: the node to find the children/dependents of
- */
-void DEG_node_get_children(struct ListBase *result, const struct DepsNode *node);
-
-
-/* Get list of nodes which given node directly depends on
- *
- * > result: list to write results to
- * < node: the node to find the dependencies of
- */
-void DEG_node_get_dependencies(struct ListBase *result, const struct DepsNode *node);
-
-
-/* Topology Queries (Subgraph) -------------------- */
-// XXX: given that subgraphs potentially involve many interconnected nodes, we currently
-// just spit out a copy of the subgraph which matches. This works well for the cases
-// where these are used - mostly for efficient updating of subsets of the nodes.
-
-// XXX: allow supplying a filter predicate to provide further filtering/pruning?
-
-
-/* Get all descendants of a node
- *
- * That is, get the subgraph / subset of nodes which are dependent
- * on the results of the given node.
- */
-Depsgraph *DEG_node_get_descendants(const struct Depsgraph *graph, const struct DepsNode *node);
-
-
-/* Get all ancestors of a node
- *
- * That is, get the subgraph / subset of nodes which the given node
- * is dependent on in order to be evaluated.
- */
-Depsgraph *DEG_node_get_ancestors(const struct Depsgraph *graph, const struct DepsNode *node);
-
-/* ************************************************ */
-/* Higher-Level Queries */
-
-/* Get ID-blocks which would be affected if specified ID is modified
- * < only_direct: True = Only ID-blocks with direct relationships to ID-block will be returned
- *
- * > result: (LinkData : ID) a list of ID-blocks matching the specified criteria
- * > returns: number of matching ID-blocks
- */
-size_t DEG_query_affected_ids(struct ListBase *result, const struct ID *id, const bool only_direct);
-
-
-/* Get ID-blocks which are needed to update/evaluate specified ID
- * < only_direct: True = Only ID-blocks with direct relationships to ID-block will be returned
- *
- * > result: (LinkData : ID) a list of ID-blocks matching the specified criteria
- * > returns: number of matching ID-blocks
- */
-size_t DEG_query_required_ids(struct ListBase *result, const struct ID *id, const bool only_direct);
-
-/* ************************************************ */
-
/* Check if given ID type was tagged for update. */
bool DEG_id_type_tagged(struct Main *bmain, short idtype);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
new file mode 100644
index 00000000000..9f80c21a6a4
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -0,0 +1,129 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/build/deg_builder.cc
+ * \ingroup depsgraph
+ */
+
+#include "intern/builder/deg_builder.h"
+
+// TODO(sergey): Use own wrapper over STD.
+#include <stack>
+
+#include "DNA_anim_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+#include "intern/depsgraph.h"
+#include "intern/depsgraph_types.h"
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+string deg_fcurve_id_name(const FCurve *fcu)
+{
+ char index_buf[32];
+ // TODO(sergey): Use int-to-string utility or so.
+ BLI_snprintf(index_buf, sizeof(index_buf), "[%d]", fcu->array_index);
+ return string(fcu->rna_path) + index_buf;
+}
+
+void deg_graph_build_finalize(Depsgraph *graph)
+{
+ std::stack<OperationDepsNode *> stack;
+
+ foreach (OperationDepsNode *node, graph->operations) {
+ IDDepsNode *id_node = node->owner->owner;
+ node->done = 0;
+ node->num_links_pending = 0;
+ foreach (DepsRelation *rel, node->outlinks) {
+ if ((rel->from->type == DEPSNODE_TYPE_OPERATION) &&
+ (rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
+ {
+ ++node->num_links_pending;
+ }
+ }
+ if (node->num_links_pending == 0) {
+ stack.push(node);
+ node->done = 1;
+ }
+ node->owner->layers = id_node->layers;
+ id_node->id->tag |= LIB_TAG_DOIT;
+ }
+
+ while (!stack.empty()) {
+ OperationDepsNode *node = stack.top();
+ stack.pop();
+ /* Flush layers to parents. */
+ foreach (DepsRelation *rel, node->inlinks) {
+ if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ OperationDepsNode *from = (OperationDepsNode *)rel->from;
+ from->owner->layers |= node->owner->layers;
+ }
+ }
+ /* Schedule parent nodes. */
+ foreach (DepsRelation *rel, node->inlinks) {
+ if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ OperationDepsNode *from = (OperationDepsNode *)rel->from;
+ if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
+ BLI_assert(from->num_links_pending > 0);
+ --from->num_links_pending;
+ }
+ if (from->num_links_pending == 0 && from->done == 0) {
+ stack.push(from);
+ from->done = 1;
+ }
+ }
+ }
+ }
+
+ /* Re-tag IDs for update if it was tagged before the relations update tag. */
+ GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
+ {
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp, id_node->components)
+ {
+ id_node->layers |= comp->layers;
+ }
+ GHASH_FOREACH_END();
+
+ ID *id = id_node->id;
+ if (id->tag & LIB_TAG_ID_RECALC_ALL &&
+ id->tag & LIB_TAG_DOIT)
+ {
+ id_node->tag_update(graph);
+ id->tag &= ~LIB_TAG_DOIT;
+ }
+ id_node->finalize_build();
+ }
+ GHASH_FOREACH_END();
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h
new file mode 100644
index 00000000000..7ecb4b20684
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder.h
@@ -0,0 +1,46 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/build/deg_builder.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/depsgraph_types.h"
+
+struct FCurve;
+
+namespace DEG {
+
+struct Depsgraph;
+
+/* Get unique identifier for FCurves and Drivers */
+string deg_fcurve_id_name(const FCurve *fcu);
+
+void deg_graph_build_finalize(struct Depsgraph *graph);
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/util/depsgraph_util_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
index 5eae8c087ad..225cc64ae4d 100644
--- a/source/blender/depsgraph/util/depsgraph_util_cycle.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
@@ -23,28 +23,30 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/util/depsgraph_util_cycle.cc
+/** \file blender/depsgraph/intern/builder/deg_builder_cycle.cc
* \ingroup depsgraph
*/
+#include "intern/builder/deg_builder_cycle.h"
+
+// TOO(sergey): Use some wrappers over those?
#include <cstdio>
#include <cstdlib>
#include <stack>
extern "C" {
#include "BLI_utildefines.h"
+}
-#include "DNA_ID.h"
+#include "util/deg_util_foreach.h"
-#include "RNA_access.h"
-#include "RNA_types.h"
-}
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
-#include "depsgraph_util_cycle.h"
-#include "depsgraph.h"
-#include "depsnode.h"
-#include "depsnode_component.h"
-#include "depsnode_operation.h"
+#include "intern/depsgraph.h"
+
+namespace DEG {
struct StackEntry {
OperationDepsNode *node;
@@ -62,17 +64,9 @@ void deg_graph_detect_cycles(Depsgraph *graph)
const int NODE_IN_STACK = 2;
std::stack<StackEntry> traversal_stack;
- for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
- it_op != graph->operations.end();
- ++it_op)
- {
- OperationDepsNode *node = *it_op;
+ foreach (OperationDepsNode *node, graph->operations) {
bool has_inlinks = false;
- for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin();
- it_rel != node->inlinks.end();
- ++it_rel)
- {
- DepsRelation *rel = *it_rel;
+ foreach (DepsRelation *rel, node->inlinks) {
if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
has_inlinks = true;
}
@@ -94,11 +88,7 @@ void deg_graph_detect_cycles(Depsgraph *graph)
StackEntry &entry = traversal_stack.top();
OperationDepsNode *node = entry.node;
bool all_child_traversed = true;
- for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
- it_rel != node->outlinks.end();
- ++it_rel)
- {
- DepsRelation *rel = *it_rel;
+ foreach (DepsRelation *rel, node->outlinks) {
if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
OperationDepsNode *to = (OperationDepsNode *)rel->to;
if (to->done == NODE_IN_STACK) {
@@ -138,3 +128,5 @@ void deg_graph_detect_cycles(Depsgraph *graph)
}
}
}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/util/depsgraph_util_cycle.h b/source/blender/depsgraph/intern/builder/deg_builder_cycle.h
index fac38b61057..386fbd80d19 100644
--- a/source/blender/depsgraph/util/depsgraph_util_cycle.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.h
@@ -23,15 +23,18 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/util/depsgraph_util_cycle.h
+/** \file blender/depsgraph/intern/builder/deg_builder_cycle.h
* \ingroup depsgraph
*/
-#ifndef __DEPSGRAPH_UTIL_CYCLE_H__
-#define __DEPSGRAPH_UTIL_CYCLE_H__
+
+#pragma once
+
+namespace DEG {
struct Depsgraph;
+/* Detect and solve dependency cycles. */
void deg_graph_detect_cycles(Depsgraph *graph);
-#endif /* __DEPSGRAPH_UTIL_CYCLE_H__ */
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_build_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index c29532a02c6..17b6acfd680 100644
--- a/source/blender/depsgraph/intern/depsgraph_build_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -24,12 +24,14 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/intern/depsgraph_build_nodes.cc
+/** \file blender/depsgraph/intern/builder/deg_build_nodes.cc
* \ingroup depsgraph
*
* Methods for constructing depsgraph's nodes
*/
+#include "intern/builder/deg_builder_nodes.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -95,12 +97,14 @@ extern "C" {
#include "RNA_types.h"
} /* extern "C" */
-#include "depsnode.h"
-#include "depsnode_component.h"
-#include "depsnode_operation.h"
-#include "depsgraph_types.h"
-#include "depsgraph_build.h"
-#include "depsgraph_intern.h"
+#include "intern/builder/deg_builder.h"
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+#include "intern/depsgraph_types.h"
+#include "intern/depsgraph_intern.h"
+
+namespace DEG {
/* ************ */
/* Node Builder */
@@ -215,6 +219,17 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
return add_operation_node(comp_node, optype, op, opcode, description);
}
+OperationDepsNode *DepsgraphNodeBuilder::add_operation_node(
+ ID *id,
+ eDepsNode_Type comp_type,
+ eDepsOperation_Type optype,
+ DepsEvalOperationCb op,
+ eDepsOperation_Code opcode,
+ const string& description)
+{
+ return add_operation_node(id, comp_type, "", optype, op, opcode, description);
+}
+
bool DepsgraphNodeBuilder::has_operation_node(ID *id,
eDepsNode_Type comp_type,
const string &comp_name,
@@ -235,6 +250,14 @@ OperationDepsNode *DepsgraphNodeBuilder::find_operation_node(
return comp_node->has_operation(opcode, description);
}
+OperationDepsNode *DepsgraphNodeBuilder::find_operation_node(
+ ID *id,
+ eDepsNode_Type comp_type,
+ eDepsOperation_Code opcode,
+ const string& description)
+{
+ return find_operation_node(id, comp_type, "", opcode, description);
+}
/* **** Build functions for entity nodes **** */
@@ -341,7 +364,7 @@ SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group)
return NULL;
/* create new subgraph's data */
- Depsgraph *subgraph = DEG_graph_new();
+ Depsgraph *subgraph = reinterpret_cast<Depsgraph *>(DEG_graph_new());
DepsgraphNodeBuilder subgraph_builder(m_bmain, subgraph);
@@ -379,11 +402,11 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
IDDepsNode *id_node = add_id_node(&ob->id);
id_node->layers = base->lay;
+ ob->customdata_mask = 0;
/* standard components */
build_object_transform(scene, ob);
-
/* object data */
if (ob->data) {
/* type-specific data... */
@@ -1187,3 +1210,5 @@ void DepsgraphNodeBuilder::build_gpencil(bGPdata *gpd)
*/
build_animdata(gpd_id);
}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
new file mode 100644
index 00000000000..6ee0b8406a1
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -0,0 +1,153 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Lukas Toenne
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_nodes.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#include "intern/depsgraph_types.h"
+
+struct Base;
+struct bGPdata;
+struct ListBase;
+struct GHash;
+struct ID;
+struct FCurve;
+struct Group;
+struct Key;
+struct Main;
+struct Material;
+struct MTex;
+struct bNodeTree;
+struct Object;
+struct bPoseChannel;
+struct bConstraint;
+struct Scene;
+struct Tex;
+struct World;
+
+struct PropertyRNA;
+
+namespace DEG {
+
+struct Depsgraph;
+struct DepsNode;
+struct RootDepsNode;
+struct SubgraphDepsNode;
+struct IDDepsNode;
+struct TimeSourceDepsNode;
+struct ComponentDepsNode;
+struct OperationDepsNode;
+
+struct DepsgraphNodeBuilder {
+ DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph);
+ ~DepsgraphNodeBuilder();
+
+ RootDepsNode *add_root_node();
+ IDDepsNode *add_id_node(ID *id);
+ TimeSourceDepsNode *add_time_source(ID *id);
+
+ ComponentDepsNode *add_component_node(ID *id,
+ eDepsNode_Type comp_type,
+ const string& comp_name = "");
+
+ OperationDepsNode *add_operation_node(ComponentDepsNode *comp_node,
+ eDepsOperation_Type optype,
+ DepsEvalOperationCb op,
+ eDepsOperation_Code opcode,
+ const string& description = "");
+ OperationDepsNode *add_operation_node(ID *id,
+ eDepsNode_Type comp_type,
+ const string& comp_name,
+ eDepsOperation_Type optype,
+ DepsEvalOperationCb op,
+ eDepsOperation_Code opcode,
+ const string& description = "");
+ OperationDepsNode *add_operation_node(ID *id,
+ eDepsNode_Type comp_type,
+ eDepsOperation_Type optype,
+ DepsEvalOperationCb op,
+ eDepsOperation_Code opcode,
+ const string& description = "");
+
+ bool has_operation_node(ID *id,
+ eDepsNode_Type comp_type,
+ const string& comp_name,
+ eDepsOperation_Code opcode,
+ const string& description = "");
+
+ OperationDepsNode *find_operation_node(ID *id,
+ eDepsNode_Type comp_type,
+ const string &comp_name,
+ eDepsOperation_Code opcode,
+ const string &description = "");
+
+ OperationDepsNode *find_operation_node(ID *id,
+ eDepsNode_Type comp_type,
+ eDepsOperation_Code opcode,
+ const string &description = "");
+
+ void build_scene(Main *bmain, Scene *scene);
+ SubgraphDepsNode *build_subgraph(Group *group);
+ void build_group(Scene *scene, Base *base, Group *group);
+ void build_object(Scene *scene, Base *base, Object *ob);
+ void build_object_transform(Scene *scene, Object *ob);
+ void build_object_constraints(Scene *scene, Object *ob);
+ void build_pose_constraints(Object *ob, bPoseChannel *pchan);
+ void build_rigidbody(Scene *scene);
+ void build_particles(Scene *scene, Object *ob);
+ void build_animdata(ID *id);
+ OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
+ void build_ik_pose(Scene *scene,
+ Object *ob,
+ bPoseChannel *pchan,
+ bConstraint *con);
+ void build_splineik_pose(Scene *scene,
+ Object *ob,
+ bPoseChannel *pchan,
+ bConstraint *con);
+ void build_rig(Scene *scene, Object *ob);
+ void build_proxy_rig(Object *ob);
+ void build_shapekeys(Key *key);
+ void build_obdata_geom(Scene *scene, Object *ob);
+ void build_camera(Object *ob);
+ void build_lamp(Object *ob);
+ void build_nodetree(DepsNode *owner_node, bNodeTree *ntree);
+ void build_material(DepsNode *owner_node, Material *ma);
+ void build_texture(DepsNode *owner_node, Tex *tex);
+ void build_texture_stack(DepsNode *owner_node, MTex **texture_stack);
+ void build_world(World *world);
+ void build_compositor(Scene *scene);
+ void build_gpencil(bGPdata *gpd);
+
+protected:
+ Main *m_bmain;
+ Depsgraph *m_graph;
+};
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/util/depsgraph_util_pchanmap.cc b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
index 80b37ec622d..0e78df52ff8 100644
--- a/source/blender/depsgraph/util/depsgraph_util_pchanmap.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
@@ -24,11 +24,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/util/depsgraph_util_pchanmap.cc
+/** \file blender/depsgraph/intern/builder/deg_builder_pchanmap.h
* \ingroup depsgraph
*/
-#include "depsgraph_util_pchanmap.h"
+#include "intern/builder/deg_builder_pchanmap.h"
#include <stdio.h>
#include <string.h>
@@ -38,6 +38,8 @@ extern "C" {
#include "BLI_ghash.h"
}
+namespace DEG {
+
static void free_rootpchanmap_valueset(void *val)
{
/* Just need to free the set itself - the names stored are all references. */
@@ -48,13 +50,13 @@ static void free_rootpchanmap_valueset(void *val)
RootPChanMap::RootPChanMap()
{
/* Just create empty map. */
- m_map = BLI_ghash_str_new("RootPChanMap");
+ map_ = BLI_ghash_str_new("RootPChanMap");
}
RootPChanMap::~RootPChanMap()
{
/* Free the map, and all the value sets. */
- BLI_ghash_free(m_map, NULL, free_rootpchanmap_valueset);
+ BLI_ghash_free(map_, NULL, free_rootpchanmap_valueset);
}
/* Debug contents of map */
@@ -64,7 +66,7 @@ void RootPChanMap::print_debug()
GSetIterator it2;
printf("Root PChan Map:\n");
- GHASH_ITER(it1, m_map) {
+ GHASH_ITER(it1, map_) {
const char *item = (const char *)BLI_ghashIterator_getKey(&it1);
GSet *values = (GSet *)BLI_ghashIterator_getValue(&it1);
@@ -80,11 +82,11 @@ void RootPChanMap::print_debug()
/* Add a mapping. */
void RootPChanMap::add_bone(const char *bone, const char *root)
{
- if (BLI_ghash_haskey(m_map, bone)) {
+ if (BLI_ghash_haskey(map_, bone)) {
/* Add new entry, but only add the root if it doesn't already
* exist in there.
*/
- GSet *values = (GSet *)BLI_ghash_lookup(m_map, bone);
+ GSet *values = (GSet *)BLI_ghash_lookup(map_, bone);
BLI_gset_add(values, (void *)root);
}
else {
@@ -92,7 +94,7 @@ void RootPChanMap::add_bone(const char *bone, const char *root)
GSet *values = BLI_gset_new(BLI_ghashutil_strhash_p,
BLI_ghashutil_strcmp,
"RootPChanMap Value Set");
- BLI_ghash_insert(m_map, (void *)bone, (void *)values);
+ BLI_ghash_insert(map_, (void *)bone, (void *)values);
/* Add new entry now. */
BLI_gset_insert(values, (void *)root);
@@ -103,20 +105,20 @@ void RootPChanMap::add_bone(const char *bone, const char *root)
bool RootPChanMap::has_common_root(const char *bone1, const char *bone2)
{
/* Ensure that both are in the map... */
- if (BLI_ghash_haskey(m_map, bone1) == false) {
+ if (BLI_ghash_haskey(map_, bone1) == false) {
//fprintf("RootPChanMap: bone1 '%s' not found (%s => %s)\n", bone1, bone1, bone2);
//print_debug();
return false;
}
- if (BLI_ghash_haskey(m_map, bone2) == false) {
+ if (BLI_ghash_haskey(map_, bone2) == false) {
//fprintf("RootPChanMap: bone2 '%s' not found (%s => %s)\n", bone2, bone1, bone2);
//print_debug();
return false;
}
- GSet *bone1_roots = (GSet *)BLI_ghash_lookup(m_map, (void *)bone1);
- GSet *bone2_roots = (GSet *)BLI_ghash_lookup(m_map, (void *)bone2);
+ GSet *bone1_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone1);
+ GSet *bone2_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone2);
GSetIterator it1, it2;
GSET_ITER(it1, bone1_roots) {
@@ -134,3 +136,5 @@ bool RootPChanMap::has_common_root(const char *bone1, const char *bone2)
//fprintf("RootPChanMap: No common root found (%s => %s)\n", bone1, bone2);
return false;
}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/util/depsgraph_util_pchanmap.h b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h
index b7f4c495933..233d8602fce 100644
--- a/source/blender/depsgraph/util/depsgraph_util_pchanmap.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h
@@ -24,12 +24,15 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/util/depsgraph_util_pchanmap.h
+/** \file blender/depsgraph/intern/builder/deg_builder_pchanmap.h
* \ingroup depsgraph
*/
-#ifndef __DEPSGRAPH_UTIL_PCHANMAP_H__
-#define __DEPSGRAPH_UTIL_PCHANMAP_H__
+#pragma once
+
+struct GHash;
+
+namespace DEG {
struct RootPChanMap {
/* ctor and dtor - Create and free the internal map respectively. */
@@ -45,7 +48,7 @@ struct RootPChanMap {
/* Check if there's a common root bone between two bones. */
bool has_common_root(const char *bone1, const char *bone2);
-private:
+protected:
/* The actual map:
* - Keys are "strings" (const char *) - not dynamically allocated.
* - Values are "sets" (const char *) - not dynamically allocated.
@@ -53,7 +56,7 @@ private:
* We don't use the C++ maps here, as it's more convenient to use
* Blender's GHash and be able to compare by-value instead of by-ref.
*/
- struct GHash *m_map;
+ struct GHash *map_;
};
-#endif /* __DEPSGRAPH_UTIL_PCHANMAP_H__ */
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_build_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 23d3b391f8a..6564292e7f4 100644
--- a/source/blender/depsgraph/intern/depsgraph_build_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -24,12 +24,14 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/intern/depsgraph_build_relations.cc
+/** \file blender/depsgraph/intern/builder/deg_builder_relations.cc
* \ingroup depsgraph
*
* Methods for constructing depsgraph
*/
+#include "intern/builder/deg_builder_relations.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -91,15 +93,19 @@ extern "C" {
#include "RNA_types.h"
} /* extern "C" */
-#include "depsnode.h"
-#include "depsnode_component.h"
-#include "depsnode_operation.h"
-#include "depsgraph_build.h"
-#include "depsgraph_debug.h"
-#include "depsgraph_intern.h"
-#include "depsgraph_types.h"
+#include "intern/builder/deg_builder.h"
+#include "intern/builder/deg_builder_pchanmap.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "intern/depsgraph_intern.h"
+#include "intern/depsgraph_types.h"
+
+#include "util/deg_util_foreach.h"
-#include "depsgraph_util_pchanmap.h"
+namespace DEG {
/* ***************** */
/* Relations Builder */
@@ -302,6 +308,19 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
if (scene->gpd) {
build_gpencil(&scene->id, scene->gpd);
}
+
+ for (Depsgraph::OperationNodes::const_iterator it_op = m_graph->operations.begin();
+ it_op != m_graph->operations.end();
+ ++it_op)
+ {
+ OperationDepsNode *node = *it_op;
+ IDDepsNode *id_node = node->owner->owner;
+ ID *id = id_node->id;
+ if (GS(id->name) == ID_OB) {
+ Object *object = (Object *)id;
+ object->customdata_mask |= node->customdata_mask;
+ }
+ }
}
void DepsgraphRelationBuilder::build_group(Main *bmain,
@@ -466,8 +485,12 @@ void DepsgraphRelationBuilder::build_object_parent(Object *ob)
{
ComponentKey parent_key(&ob->parent->id, DEPSNODE_TYPE_GEOMETRY);
add_relation(parent_key, ob_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Vertex Parent");
+
/* XXX not sure what this is for or how you could be done properly - lukas */
- //parent_node->customdata_mask |= CD_MASK_ORIGINDEX;
+ OperationDepsNode *parent_node = find_operation_node(parent_key);
+ if (parent_node != NULL) {
+ parent_node->customdata_mask |= CD_MASK_ORIGINDEX;
+ }
ComponentKey transform_key(&ob->parent->id, DEPSNODE_TYPE_TRANSFORM);
add_relation(transform_key, ob_key, DEPSREL_TYPE_TRANSFORM, "Vertex Parent TFM");
@@ -618,7 +641,10 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
add_relation(target_key, constraint_op_key, DEPSREL_TYPE_GEOMETRY_EVAL, cti->name);
if (ct->tar->type == OB_MESH) {
- //node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+ OperationDepsNode *node2 = find_operation_node(target_key);
+ if (node2 != NULL) {
+ node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+ }
}
}
else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
@@ -759,8 +785,7 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
if (arm_node && bone_name) {
/* find objects which use this, and make their eval callbacks depend on this */
- DEPSNODE_RELATIONS_ITER_BEGIN(arm_node->outlinks, rel)
- {
+ foreach (DepsRelation *rel, arm_node->outlinks) {
IDDepsNode *to_node = (IDDepsNode *)rel->to;
/* we only care about objects with pose data which use this... */
@@ -774,7 +799,6 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
}
}
}
- DEPSNODE_RELATIONS_ITER_END;
/* free temp data */
MEM_freeN(bone_name);
@@ -1067,7 +1091,10 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
if (data->tar->type == OB_MESH) {
- //node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+ OperationDepsNode *node2 = find_operation_node(target_key);
+ if (node2 != NULL) {
+ node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+ }
}
}
else {
@@ -1099,7 +1126,10 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
if (data->poletar->type == OB_MESH) {
- //node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+ OperationDepsNode *node2 = find_operation_node(target_key);
+ if (node2 != NULL) {
+ node2->customdata_mask |= CD_MASK_MDEFORMVERT;
+ }
}
}
else {
@@ -1475,13 +1505,18 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
if (mti->updateDepsgraph) {
DepsNodeHandle handle = create_node_handle(mod_key);
- mti->updateDepsgraph(md, bmain, scene, ob, &handle);
+ mti->updateDepsgraph(
+ md,
+ bmain,
+ scene,
+ ob,
+ reinterpret_cast< ::DepsNodeHandle* >(&handle));
}
if (BKE_object_modifier_use_time(ob, md)) {
TimeSourceKey time_src_key;
add_relation(time_src_key, mod_key, DEPSREL_TYPE_TIME, "Time Source");
-
+
/* Hacky fix for T45633 (Animated modifiers aren't updated)
*
* This check works because BKE_object_modifier_use_time() tests
@@ -1791,3 +1826,4 @@ bool DepsgraphRelationBuilder::needs_animdata_node(ID *id)
return false;
}
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_build.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index af61ab4eb8b..c0bf82becda 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -24,12 +24,27 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/intern/depsgraph_build.h
+/** \file blender/depsgraph/intern/builder/deg_builder_relations.h
* \ingroup depsgraph
*/
-#ifndef __DEPSGRAPH_BUILD_H__
-#define __DEPSGRAPH_BUILD_H__
+#pragma once
+
+#include <cstdio>
+
+#include "intern/depsgraph_types.h"
+
+#include "DNA_ID.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+
+#include "intern/depsgraph_types.h"
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_operation.h"
struct Base;
struct bGPdata;
@@ -52,6 +67,8 @@ struct World;
struct PropertyRNA;
+namespace DEG {
+
struct Depsgraph;
struct DepsNode;
struct DepsNodeHandle;
@@ -63,74 +80,6 @@ struct ComponentDepsNode;
struct OperationDepsNode;
struct RootPChanMap;
-struct DepsgraphNodeBuilder {
- DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph);
- ~DepsgraphNodeBuilder();
-
- RootDepsNode *add_root_node();
- IDDepsNode *add_id_node(ID *id);
- TimeSourceDepsNode *add_time_source(ID *id);
-
- ComponentDepsNode *add_component_node(ID *id, eDepsNode_Type comp_type, const string &comp_name = "");
-
- OperationDepsNode *add_operation_node(ComponentDepsNode *comp_node, eDepsOperation_Type optype,
- DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &description = "");
- OperationDepsNode *add_operation_node(ID *id, eDepsNode_Type comp_type, const string &comp_name, eDepsOperation_Type optype,
- DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &description = "");
- OperationDepsNode *add_operation_node(ID *id, eDepsNode_Type comp_type, eDepsOperation_Type optype,
- DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &description = "")
- {
- return add_operation_node(id, comp_type, "", optype, op, opcode, description);
- }
-
- bool has_operation_node(ID *id, eDepsNode_Type comp_type, const string &comp_name,
- eDepsOperation_Code opcode, const string &description = "");
-
- OperationDepsNode *find_operation_node(ID *id,
- eDepsNode_Type comp_type,
- const string &comp_name,
- eDepsOperation_Code opcode,
- const string &description = "");
-
- OperationDepsNode *find_operation_node(ID *id,
- eDepsNode_Type comp_type,
- eDepsOperation_Code opcode,
- const string &description = "")
- {
- return find_operation_node(id, comp_type, "", opcode, description);
- }
-
- void build_scene(Main *bmain, Scene *scene);
- SubgraphDepsNode *build_subgraph(Group *group);
- void build_group(Scene *scene, Base *base, Group *group);
- void build_object(Scene *scene, Base *base, Object *ob);
- void build_object_transform(Scene *scene, Object *ob);
- void build_object_constraints(Scene *scene, Object *ob);
- void build_pose_constraints(Object *ob, bPoseChannel *pchan);
- void build_rigidbody(Scene *scene);
- void build_animdata(ID *id);
- OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
- void build_ik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con);
- void build_splineik_pose(Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con);
- void build_rig(Scene *scene, Object *ob);
- void build_proxy_rig(Object *ob);
- void build_shapekeys(Key *key);
- void build_obdata_geom(Scene *scene, Object *ob);
- void build_camera(Object *ob);
- void build_lamp(Object *ob);
- void build_nodetree(DepsNode *owner_node, bNodeTree *ntree);
- void build_material(DepsNode *owner_node, Material *ma);
- void build_texture(DepsNode *owner_node, Tex *tex);
- void build_texture_stack(DepsNode *owner_node, MTex **texture_stack);
- void build_world(World *world);
- void build_compositor(Scene *scene);
- void build_gpencil(bGPdata *gpd);
-
-private:
- Main *m_bmain;
- Depsgraph *m_graph;
-};
-
struct RootKey
{
RootKey() {}
@@ -163,7 +112,7 @@ struct ComponentKey
const char *idname = (id) ? id->name : "<None>";
char typebuf[5];
- sprintf(typebuf, "%d", type);
+ BLI_snprintf(typebuf, sizeof(typebuf), "%d", type);
return string("ComponentKey(") + idname + ", " + typebuf + ", '" + name + "')";
}
@@ -203,7 +152,7 @@ struct OperationKey
string identifier() const
{
char typebuf[5];
- sprintf(typebuf, "%d", component_type);
+ BLI_snprintf(typebuf, sizeof(typebuf), "%d", component_type);
return string("OperationKey(") + "t: " + typebuf + ", cn: '" + component_name + "', c: " + DEG_OPNAMES[opcode] + ", n: '" + name + "')";
}
@@ -244,29 +193,45 @@ struct DepsgraphRelationBuilder
DepsgraphRelationBuilder(Depsgraph *graph);
template <typename KeyFrom, typename KeyTo>
- void add_relation(const KeyFrom &key_from, const KeyTo &key_to,
- eDepsRelation_Type type, const char *description);
+ void add_relation(const KeyFrom& key_from,
+ const KeyTo& key_to,
+ eDepsRelation_Type type,
+ const char *description);
template <typename KeyTo>
- void add_relation(const TimeSourceKey &key_from, const KeyTo &key_to,
- eDepsRelation_Type type, const char *description);
+ void add_relation(const TimeSourceKey& key_from,
+ const KeyTo& key_to,
+ eDepsRelation_Type type,
+ const char *description);
template <typename KeyType>
- void add_node_handle_relation(const KeyType &key_from, const DepsNodeHandle *handle,
- eDepsRelation_Type type, const char *description);
+ void add_node_handle_relation(const KeyType& key_from,
+ const DepsNodeHandle *handle,
+ eDepsRelation_Type type,
+ const char *description);
void build_scene(Main *bmain, Scene *scene);
void build_group(Main *bmain, Scene *scene, Object *object, Group *group);
void build_object(Main *bmain, Scene *scene, Object *ob);
void build_object_parent(Object *ob);
- void build_constraints(Scene *scene, ID *id, eDepsNode_Type component_type, const char *component_subdata,
- ListBase *constraints, RootPChanMap *root_map);
+ void build_constraints(Scene *scene, ID *id,
+ eDepsNode_Type component_type,
+ const char *component_subdata,
+ ListBase *constraints,
+ RootPChanMap *root_map);
void build_animdata(ID *id);
void build_driver(ID *id, FCurve *fcurve);
void build_world(World *world);
void build_rigidbody(Scene *scene);
- void build_ik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map);
- void build_splineik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con, RootPChanMap *root_map);
+ void build_particles(Scene *scene, Object *ob);
+ void build_ik_pose(Object *ob,
+ bPoseChannel *pchan,
+ bConstraint *con,
+ RootPChanMap *root_map);
+ void build_splineik_pose(Object *ob,
+ bPoseChannel *pchan,
+ bConstraint *con,
+ RootPChanMap *root_map);
void build_rig(Scene *scene, Object *ob);
void build_proxy_rig(Object *ob);
void build_shapekeys(ID *obdata, Key *key);
@@ -280,6 +245,9 @@ struct DepsgraphRelationBuilder
void build_compositor(Scene *scene);
void build_gpencil(ID *owner, bGPdata *gpd);
+ template <typename KeyType>
+ OperationDepsNode *find_operation_node(const KeyType &key);
+
protected:
RootDepsNode *find_node(const RootKey &key) const;
TimeSourceDepsNode *find_node(const TimeSourceKey &key) const;
@@ -288,12 +256,17 @@ protected:
DepsNode *find_node(const RNAPathKey &key) const;
OperationDepsNode *has_node(const OperationKey &key) const;
- void add_time_relation(TimeSourceDepsNode *timesrc, DepsNode *node_to, const char *description);
- void add_operation_relation(OperationDepsNode *node_from, OperationDepsNode *node_to,
- eDepsRelation_Type type, const char *description);
+ void add_time_relation(TimeSourceDepsNode *timesrc,
+ DepsNode *node_to,
+ const char *description);
+ void add_operation_relation(OperationDepsNode *node_from,
+ OperationDepsNode *node_to,
+ eDepsRelation_Type type,
+ const char *description);
template <typename KeyType>
- DepsNodeHandle create_node_handle(const KeyType &key, const string &default_name = "");
+ DepsNodeHandle create_node_handle(const KeyType& key,
+ const string& default_name = "");
bool needs_animdata_node(ID *id);
@@ -318,8 +291,11 @@ struct DepsNodeHandle
/* Utilities for Builders ----------------------------------------------------- */
-/* Get unique identifier for FCurves and Drivers */
-string deg_fcurve_id_name(const FCurve *fcu);
+template <typename KeyType>
+OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType& key) {
+ DepsNode *node = find_node(key);
+ return node != NULL ? node->get_exit_operation() : NULL;
+}
template <typename KeyFrom, typename KeyTo>
void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
@@ -375,10 +351,11 @@ void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from,
}
template <typename KeyType>
-void DepsgraphRelationBuilder::add_node_handle_relation(const KeyType &key_from,
- const DepsNodeHandle *handle,
- eDepsRelation_Type type,
- const char *description)
+void DepsgraphRelationBuilder::add_node_handle_relation(
+ const KeyType &key_from,
+ const DepsNodeHandle *handle,
+ eDepsRelation_Type type,
+ const char *description)
{
DepsNode *node_from = find_node(key_from);
OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
@@ -397,10 +374,11 @@ void DepsgraphRelationBuilder::add_node_handle_relation(const KeyType &key_from,
}
template <typename KeyType>
-DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(const KeyType &key,
- const string &default_name)
+DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(
+ const KeyType &key,
+ const string &default_name)
{
return DepsNodeHandle(this, find_node(key), default_name);
}
-#endif /* __DEPSGRAPH_BUILD_H__ */
+} // namespace DEG
diff --git a/source/blender/depsgraph/util/depsgraph_util_transitive.cc b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
index 98192a9540f..0322ef7fa1d 100644
--- a/source/blender/depsgraph/util/depsgraph_util_transitive.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
@@ -24,26 +24,25 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/util/depsgraph_util_transitive.cc
+/** \file blender/depsgraph/intern/builder/deg_builder_transitive.cc
* \ingroup depsgraph
*/
+#include "intern/builder/deg_builder_transitive.h"
+
extern "C" {
#include "MEM_guardedalloc.h"
+}
-#include "BLI_utildefines.h"
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
-#include "DNA_ID.h"
+#include "intern/depsgraph.h"
-#include "RNA_access.h"
-#include "RNA_types.h"
-}
+#include "util/deg_util_foreach.h"
-#include "depsgraph_util_transitive.h"
-#include "depsgraph.h"
-#include "depsnode.h"
-#include "depsnode_component.h"
-#include "depsnode_operation.h"
+namespace DEG {
/* -------------------------------------------------- */
@@ -67,16 +66,11 @@ enum {
static void deg_graph_tag_paths_recursive(DepsNode *node)
{
- if (node->done & OP_VISITED)
+ if (node->done & OP_VISITED) {
return;
+ }
node->done |= OP_VISITED;
-
- for (OperationDepsNode::Relations::const_iterator it = node->inlinks.begin();
- it != node->inlinks.end();
- ++it)
- {
- DepsRelation *rel = *it;
-
+ foreach (DepsRelation *rel, node->inlinks) {
deg_graph_tag_paths_recursive(rel->from);
/* Do this only in inlinks loop, so the target node does not get
* flagged.
@@ -87,18 +81,9 @@ static void deg_graph_tag_paths_recursive(DepsNode *node)
void deg_graph_transitive_reduction(Depsgraph *graph)
{
- for (Depsgraph::OperationNodes::const_iterator it_target = graph->operations.begin();
- it_target != graph->operations.end();
- ++it_target)
- {
- OperationDepsNode *target = *it_target;
-
+ foreach (OperationDepsNode *target, graph->operations) {
/* Clear tags. */
- for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
- it != graph->operations.end();
- ++it)
- {
- OperationDepsNode *node = *it;
+ foreach (OperationDepsNode *node, graph->operations) {
node->done = 0;
}
@@ -107,19 +92,14 @@ void deg_graph_transitive_reduction(Depsgraph *graph)
* flagged.
*/
target->done |= OP_VISITED;
- for (OperationDepsNode::Relations::const_iterator it = target->inlinks.begin();
- it != target->inlinks.end();
- ++it)
- {
- DepsRelation *rel = *it;
-
+ foreach (DepsRelation *rel, target->inlinks) {
deg_graph_tag_paths_recursive(rel->from);
}
- /* Eemove redundant paths to the target. */
+ /* Remove redundant paths to the target. */
for (DepsNode::Relations::const_iterator it_rel = target->inlinks.begin();
it_rel != target->inlinks.end();
- )
+ )
{
DepsRelation *rel = *it_rel;
/* Increment in advance, so we can safely remove the relation. */
@@ -137,3 +117,5 @@ void deg_graph_transitive_reduction(Depsgraph *graph)
}
}
}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/util/depsgraph_util_transitive.h b/source/blender/depsgraph/intern/builder/deg_builder_transitive.h
index a80a1d783d7..be9d7c3ca9c 100644
--- a/source/blender/depsgraph/util/depsgraph_util_transitive.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.h
@@ -24,15 +24,17 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/util/depsgraph_util_transitive.h
+/** \file blender/depsgraph/intern/builder/deg_builder_transitive.h
* \ingroup depsgraph
*/
-#ifndef __DEPSGRAPH_UTIL_TRANSITIVE_H__
-#define __DEPSGRAPH_UTIL_TRANSITIVE_H__
+#pragma once
+
+namespace DEG {
struct Depsgraph;
+/* Performs a transitive reduction to remove redundant relations. */
void deg_graph_transitive_reduction(Depsgraph *graph);
-#endif /* __DEPSGRAPH_UTIL_TRANSITIVE_H__ */
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
new file mode 100644
index 00000000000..5ce84ee29db
--- /dev/null
+++ b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
@@ -0,0 +1,588 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Lukas Toenne
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/debug/deg_debug_graphviz.cc
+ * \ingroup depsgraph
+ *
+ * Implementation of tools for debugging the depsgraph
+ */
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
+extern "C" {
+#include "DNA_listBase.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_debug.h"
+} /* extern "C" */
+
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+
+/* ****************** */
+/* Graphviz Debugging */
+
+namespace DEG {
+
+#define NL "\r\n"
+
+/* Only one should be enabled, defines whether graphviz nodes
+ * get colored by individual types or classes.
+ */
+#define COLOR_SCHEME_NODE_CLASS 1
+//#define COLOR_SCHEME_NODE_TYPE 2
+
+static const char *deg_debug_graphviz_fontname = "helvetica";
+static float deg_debug_graphviz_graph_label_size = 20.0f;
+static float deg_debug_graphviz_node_label_size = 14.0f;
+static const int deg_debug_max_colors = 12;
+#ifdef COLOR_SCHEME_NODE_TYPE
+static const char *deg_debug_colors[] = {
+ "#a6cee3", "#1f78b4", "#b2df8a",
+ "#33a02c", "#fb9a99", "#e31a1c",
+ "#fdbf6f", "#ff7f00", "#cab2d6",
+ "#6a3d9a", "#ffff99", "#b15928",
+};
+#endif
+static const char *deg_debug_colors_light[] = {
+ "#8dd3c7", "#ffffb3", "#bebada",
+ "#fb8072", "#80b1d3", "#fdb462",
+ "#b3de69", "#fccde5", "#d9d9d9",
+ "#bc80bd", "#ccebc5", "#ffed6f",
+};
+
+#ifdef COLOR_SCHEME_NODE_TYPE
+static const int deg_debug_node_type_color_map[][2] = {
+ {DEPSNODE_TYPE_ROOT, 0},
+ {DEPSNODE_TYPE_TIMESOURCE, 1},
+ {DEPSNODE_TYPE_ID_REF, 2},
+ {DEPSNODE_TYPE_SUBGRAPH, 3},
+
+ /* Outer Types */
+ {DEPSNODE_TYPE_PARAMETERS, 4},
+ {DEPSNODE_TYPE_PROXY, 5},
+ {DEPSNODE_TYPE_ANIMATION, 6},
+ {DEPSNODE_TYPE_TRANSFORM, 7},
+ {DEPSNODE_TYPE_GEOMETRY, 8},
+ {DEPSNODE_TYPE_SEQUENCER, 9},
+ {DEPSNODE_TYPE_SHADING, 10},
+ {-1, 0}
+};
+#endif
+
+static int deg_debug_node_color_index(const DepsNode *node)
+{
+#ifdef COLOR_SCHEME_NODE_CLASS
+ /* Some special types. */
+ switch (node->type) {
+ case DEPSNODE_TYPE_ID_REF:
+ return 5;
+ case DEPSNODE_TYPE_OPERATION:
+ {
+ OperationDepsNode *op_node = (OperationDepsNode *)node;
+ if (op_node->is_noop())
+ return 8;
+ break;
+ }
+
+ default:
+ break;
+ }
+ /* Do others based on class. */
+ switch (node->tclass) {
+ case DEPSNODE_CLASS_OPERATION:
+ return 4;
+ case DEPSNODE_CLASS_COMPONENT:
+ return 1;
+ default:
+ return 9;
+ }
+#endif
+
+#ifdef COLOR_SCHEME_NODE_TYPE
+ const int (*pair)[2];
+ for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
+ if ((*pair)[0] == node->type) {
+ return (*pair)[1];
+ }
+ }
+ return -1;
+#endif
+}
+
+struct DebugContext {
+ FILE *file;
+ bool show_tags;
+ bool show_eval_priority;
+};
+
+static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) ATTR_PRINTF_FORMAT(2, 3);
+static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(ctx.file, fmt, args);
+ va_end(args);
+}
+
+static void deg_debug_graphviz_legend_color(const DebugContext &ctx,
+ const char *name,
+ const char *color)
+{
+ deg_debug_fprintf(ctx, "<TR>");
+ deg_debug_fprintf(ctx, "<TD>%s</TD>", name);
+ deg_debug_fprintf(ctx, "<TD BGCOLOR=\"%s\"></TD>", color);
+ deg_debug_fprintf(ctx, "</TR>" NL);
+}
+
+static void deg_debug_graphviz_legend(const DebugContext &ctx)
+{
+ deg_debug_fprintf(ctx, "{" NL);
+ deg_debug_fprintf(ctx, "rank = sink;" NL);
+ deg_debug_fprintf(ctx, "Legend [shape=none, margin=0, label=<" NL);
+ deg_debug_fprintf(ctx, " <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">" NL);
+ deg_debug_fprintf(ctx, "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>" NL);
+
+#ifdef COLOR_SCHEME_NODE_CLASS
+ const char **colors = deg_debug_colors_light;
+ deg_debug_graphviz_legend_color(ctx, "Operation", colors[4]);
+ deg_debug_graphviz_legend_color(ctx, "Component", colors[1]);
+ deg_debug_graphviz_legend_color(ctx, "ID Node", colors[5]);
+ deg_debug_graphviz_legend_color(ctx, "NOOP", colors[8]);
+#endif
+
+#ifdef COLOR_SCHEME_NODE_TYPE
+ const int (*pair)[2];
+ for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
+ DepsNodeFactory *nti = DEG_get_node_factory((eDepsNode_Type)(*pair)[0]);
+ deg_debug_graphviz_legend_color(ctx,
+ nti->tname().c_str(),
+ deg_debug_colors_light[(*pair)[1] % deg_debug_max_colors]);
+ }
+#endif
+
+ deg_debug_fprintf(ctx, "</TABLE>" NL);
+ deg_debug_fprintf(ctx, ">" NL);
+ deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, "}" NL);
+}
+
+static void deg_debug_graphviz_node_color(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ const char *color_default = "black";
+ const char *color_modified = "orangered4";
+ const char *color_update = "dodgerblue3";
+ const char *color = color_default;
+ if (ctx.show_tags) {
+ if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ OperationDepsNode *op_node = (OperationDepsNode *)node;
+ if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
+ color = color_modified;
+ }
+ else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ color = color_update;
+ }
+ }
+ }
+ deg_debug_fprintf(ctx, "\"%s\"", color);
+}
+
+static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ float penwidth_default = 1.0f;
+ float penwidth_modified = 4.0f;
+ float penwidth_update = 4.0f;
+ float penwidth = penwidth_default;
+ if (ctx.show_tags) {
+ if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ OperationDepsNode *op_node = (OperationDepsNode *)node;
+ if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
+ penwidth = penwidth_modified;
+ }
+ else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ penwidth = penwidth_update;
+ }
+ }
+ }
+ deg_debug_fprintf(ctx, "\"%f\"", penwidth);
+}
+
+static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ const char *defaultcolor = "gainsboro";
+ int color_index = deg_debug_node_color_index(node);
+ const char *fillcolor = color_index < 0 ? defaultcolor : deg_debug_colors_light[color_index % deg_debug_max_colors];
+ deg_debug_fprintf(ctx, "\"%s\"", fillcolor);
+}
+
+static void deg_debug_graphviz_relation_color(const DebugContext &ctx,
+ const DepsRelation *rel)
+{
+ const char *color_default = "black";
+ const char *color_error = "red4";
+ const char *color = color_default;
+ if (rel->flag & DEPSREL_FLAG_CYCLIC) {
+ color = color_error;
+ }
+ deg_debug_fprintf(ctx, "%s", color);
+}
+
+static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNode *node)
+{
+ const char *base_style = "filled"; /* default style */
+ if (ctx.show_tags) {
+ if (node->tclass == DEPSNODE_CLASS_OPERATION) {
+ OperationDepsNode *op_node = (OperationDepsNode *)node;
+ if (op_node->flag & (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE)) {
+ base_style = "striped";
+ }
+ }
+ }
+ switch (node->tclass) {
+ case DEPSNODE_CLASS_GENERIC:
+ deg_debug_fprintf(ctx, "\"%s\"", base_style);
+ break;
+ case DEPSNODE_CLASS_COMPONENT:
+ deg_debug_fprintf(ctx, "\"%s\"", base_style);
+ break;
+ case DEPSNODE_CLASS_OPERATION:
+ deg_debug_fprintf(ctx, "\"%s,rounded\"", base_style);
+ break;
+ }
+}
+
+static void deg_debug_graphviz_node_single(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ const char *shape = "box";
+ string name = node->identifier();
+ float priority = -1.0f;
+ if (node->type == DEPSNODE_TYPE_ID_REF) {
+ IDDepsNode *id_node = (IDDepsNode *)node;
+ char buf[256];
+ BLI_snprintf(buf, sizeof(buf), " (Layers: %d)", id_node->layers);
+ name += buf;
+ }
+ if (ctx.show_eval_priority && node->tclass == DEPSNODE_CLASS_OPERATION) {
+ priority = ((OperationDepsNode *)node)->eval_priority;
+ }
+ deg_debug_fprintf(ctx, "// %s\n", name.c_str());
+ deg_debug_fprintf(ctx, "\"node_%p\"", node);
+ deg_debug_fprintf(ctx, "[");
+// deg_debug_fprintf(ctx, "label=<<B>%s</B>>", name);
+ if (priority >= 0.0f) {
+ deg_debug_fprintf(ctx, "label=<%s<BR/>(<I>%.2f</I>)>",
+ name.c_str(),
+ priority);
+ }
+ else {
+ deg_debug_fprintf(ctx, "label=<%s>", name.c_str());
+ }
+ deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
+ deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_node_label_size);
+ deg_debug_fprintf(ctx, ",shape=%s", shape);
+ deg_debug_fprintf(ctx, ",style="); deg_debug_graphviz_node_style(ctx, node);
+ deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_node_color(ctx, node);
+ deg_debug_fprintf(ctx, ",fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node);
+ deg_debug_fprintf(ctx, ",penwidth="); deg_debug_graphviz_node_penwidth(ctx, node);
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, NL);
+}
+
+static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ string name = node->identifier().c_str();
+ if (node->type == DEPSNODE_TYPE_ID_REF) {
+ IDDepsNode *id_node = (IDDepsNode *)node;
+ char buf[256];
+ BLI_snprintf(buf, sizeof(buf), " (Layers: %d)", id_node->layers);
+ name += buf;
+ }
+ deg_debug_fprintf(ctx, "// %s\n", name.c_str());
+ deg_debug_fprintf(ctx, "subgraph \"cluster_%p\" {" NL, node);
+// deg_debug_fprintf(ctx, "label=<<B>%s</B>>;" NL, name);
+ deg_debug_fprintf(ctx, "label=<%s>;" NL, name.c_str());
+ deg_debug_fprintf(ctx, "fontname=\"%s\";" NL, deg_debug_graphviz_fontname);
+ deg_debug_fprintf(ctx, "fontsize=%f;" NL, deg_debug_graphviz_node_label_size);
+ deg_debug_fprintf(ctx, "margin=\"%d\";" NL, 16);
+ deg_debug_fprintf(ctx, "style="); deg_debug_graphviz_node_style(ctx, node); deg_debug_fprintf(ctx, ";" NL);
+ deg_debug_fprintf(ctx, "color="); deg_debug_graphviz_node_color(ctx, node); deg_debug_fprintf(ctx, ";" NL);
+ deg_debug_fprintf(ctx, "fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node); deg_debug_fprintf(ctx, ";" NL);
+ deg_debug_fprintf(ctx, "penwidth="); deg_debug_graphviz_node_penwidth(ctx, node); deg_debug_fprintf(ctx, ";" NL);
+ /* dummy node, so we can add edges between clusters */
+ deg_debug_fprintf(ctx, "\"node_%p\"", node);
+ deg_debug_fprintf(ctx, "[");
+ deg_debug_fprintf(ctx, "shape=%s", "point");
+ deg_debug_fprintf(ctx, ",style=%s", "invis");
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, NL);
+}
+
+static void deg_debug_graphviz_node_cluster_end(const DebugContext &ctx)
+{
+ deg_debug_fprintf(ctx, "}" NL);
+ deg_debug_fprintf(ctx, NL);
+}
+
+static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
+ const Depsgraph *graph);
+static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
+ const Depsgraph *graph);
+
+static void deg_debug_graphviz_node(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ switch (node->type) {
+ case DEPSNODE_TYPE_ID_REF:
+ {
+ const IDDepsNode *id_node = (const IDDepsNode *)node;
+ if (BLI_ghash_size(id_node->components) == 0) {
+ deg_debug_graphviz_node_single(ctx, node);
+ }
+ else {
+ deg_debug_graphviz_node_cluster_begin(ctx, node);
+ GHASH_FOREACH_BEGIN(const ComponentDepsNode *, comp, id_node->components)
+ {
+ deg_debug_graphviz_node(ctx, comp);
+ }
+ GHASH_FOREACH_END();
+ deg_debug_graphviz_node_cluster_end(ctx);
+ }
+ break;
+ }
+ case DEPSNODE_TYPE_SUBGRAPH:
+ {
+ SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
+ if (sub_node->graph) {
+ deg_debug_graphviz_node_cluster_begin(ctx, node);
+ deg_debug_graphviz_graph_nodes(ctx, sub_node->graph);
+ deg_debug_graphviz_node_cluster_end(ctx);
+ }
+ else {
+ deg_debug_graphviz_node_single(ctx, node);
+ }
+ break;
+ }
+ case DEPSNODE_TYPE_PARAMETERS:
+ case DEPSNODE_TYPE_ANIMATION:
+ case DEPSNODE_TYPE_TRANSFORM:
+ case DEPSNODE_TYPE_PROXY:
+ case DEPSNODE_TYPE_GEOMETRY:
+ case DEPSNODE_TYPE_SEQUENCER:
+ case DEPSNODE_TYPE_EVAL_POSE:
+ case DEPSNODE_TYPE_BONE:
+ case DEPSNODE_TYPE_SHADING:
+ case DEPSNODE_TYPE_EVAL_PARTICLES:
+ {
+ ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
+ if (!comp_node->operations.empty()) {
+ deg_debug_graphviz_node_cluster_begin(ctx, node);
+ foreach (DepsNode *op_node, comp_node->operations) {
+ deg_debug_graphviz_node(ctx, op_node);
+ }
+ deg_debug_graphviz_node_cluster_end(ctx);
+ }
+ else {
+ deg_debug_graphviz_node_single(ctx, node);
+ }
+ break;
+ }
+ default:
+ deg_debug_graphviz_node_single(ctx, node);
+ break;
+ }
+}
+
+static bool deg_debug_graphviz_is_cluster(const DepsNode *node)
+{
+ switch (node->type) {
+ case DEPSNODE_TYPE_ID_REF:
+ {
+ const IDDepsNode *id_node = (const IDDepsNode *)node;
+ return BLI_ghash_size(id_node->components) > 0;
+ }
+ case DEPSNODE_TYPE_SUBGRAPH:
+ {
+ SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
+ return sub_node->graph != NULL;
+ }
+ case DEPSNODE_TYPE_PARAMETERS:
+ case DEPSNODE_TYPE_ANIMATION:
+ case DEPSNODE_TYPE_TRANSFORM:
+ case DEPSNODE_TYPE_PROXY:
+ case DEPSNODE_TYPE_GEOMETRY:
+ case DEPSNODE_TYPE_SEQUENCER:
+ case DEPSNODE_TYPE_EVAL_POSE:
+ case DEPSNODE_TYPE_BONE:
+ {
+ ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
+ return !comp_node->operations.empty();
+ }
+ default:
+ return false;
+ }
+}
+
+static bool deg_debug_graphviz_is_owner(const DepsNode *node,
+ const DepsNode *other)
+{
+ switch (node->tclass) {
+ case DEPSNODE_CLASS_COMPONENT:
+ {
+ ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
+ if (comp_node->owner == other)
+ return true;
+ break;
+ }
+ case DEPSNODE_CLASS_OPERATION:
+ {
+ OperationDepsNode *op_node = (OperationDepsNode *)node;
+ if (op_node->owner == other)
+ return true;
+ else if (op_node->owner->owner == other)
+ return true;
+ break;
+ }
+ default: break;
+ }
+ return false;
+}
+
+static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
+ const DepsNode *node)
+{
+ foreach (DepsRelation *rel, node->inlinks) {
+ float penwidth = 2.0f;
+
+ const DepsNode *tail = rel->to; /* same as node */
+ const DepsNode *head = rel->from;
+ deg_debug_fprintf(ctx, "// %s -> %s\n",
+ head->identifier().c_str(),
+ tail->identifier().c_str());
+ deg_debug_fprintf(ctx, "\"node_%p\"", head);
+ deg_debug_fprintf(ctx, " -> ");
+ deg_debug_fprintf(ctx, "\"node_%p\"", tail);
+
+ deg_debug_fprintf(ctx, "[");
+ /* Note: without label an id seem necessary to avoid bugs in graphviz/dot */
+ deg_debug_fprintf(ctx, "id=\"%s\"", rel->name);
+ deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_relation_color(ctx, rel);
+ deg_debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth);
+ /* NOTE: edge from node to own cluster is not possible and gives graphviz
+ * warning, avoid this here by just linking directly to the invisible
+ * placeholder node
+ */
+ if (deg_debug_graphviz_is_cluster(tail) && !deg_debug_graphviz_is_owner(head, tail)) {
+ deg_debug_fprintf(ctx, ",ltail=\"cluster_%p\"", tail);
+ }
+ if (deg_debug_graphviz_is_cluster(head) && !deg_debug_graphviz_is_owner(tail, head)) {
+ deg_debug_fprintf(ctx, ",lhead=\"cluster_%p\"", head);
+ }
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, NL);
+ }
+}
+
+static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
+ const Depsgraph *graph)
+{
+ if (graph->root_node) {
+ deg_debug_graphviz_node(ctx, graph->root_node);
+ }
+ GHASH_FOREACH_BEGIN (DepsNode *, node, graph->id_hash)
+ {
+ deg_debug_graphviz_node(ctx, node);
+ }
+ GHASH_FOREACH_END();
+ TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
+ if (time_source != NULL) {
+ deg_debug_graphviz_node(ctx, time_source);
+ }
+}
+
+static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
+ const Depsgraph *graph)
+{
+ GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
+ {
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
+ {
+ foreach (OperationDepsNode *op_node, comp_node->operations) {
+ deg_debug_graphviz_node_relations(ctx, op_node);
+ }
+ }
+ GHASH_FOREACH_END();
+ }
+ GHASH_FOREACH_END();
+
+ TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
+ if (time_source != NULL) {
+ deg_debug_graphviz_node_relations(ctx, time_source);
+ }
+}
+
+} // namespace DEG
+
+void DEG_debug_graphviz(const Depsgraph *graph, FILE *f, const char *label, bool show_eval)
+{
+ if (!graph) {
+ return;
+ }
+
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+
+ DEG::DebugContext ctx;
+ ctx.file = f;
+ ctx.show_tags = show_eval;
+ ctx.show_eval_priority = show_eval;
+
+ DEG::deg_debug_fprintf(ctx, "digraph depgraph {" NL);
+ DEG::deg_debug_fprintf(ctx, "rankdir=LR;" NL);
+ DEG::deg_debug_fprintf(ctx, "graph [");
+ DEG::deg_debug_fprintf(ctx, "compound=true");
+ DEG::deg_debug_fprintf(ctx, ",labelloc=\"t\"");
+ DEG::deg_debug_fprintf(ctx, ",fontsize=%f", DEG::deg_debug_graphviz_graph_label_size);
+ DEG::deg_debug_fprintf(ctx, ",fontname=\"%s\"", DEG::deg_debug_graphviz_fontname);
+ DEG::deg_debug_fprintf(ctx, ",label=\"%s\"", label);
+ DEG::deg_debug_fprintf(ctx, ",splines=ortho");
+ DEG::deg_debug_fprintf(ctx, ",overlap=scalexy"); // XXX: only when using neato
+ DEG::deg_debug_fprintf(ctx, "];" NL);
+
+ DEG::deg_debug_graphviz_graph_nodes(ctx, deg_graph);
+ DEG::deg_debug_graphviz_graph_relations(ctx, deg_graph);
+
+ DEG::deg_debug_graphviz_legend(ctx);
+
+ DEG::deg_debug_fprintf(ctx, "}" NL);
+}
+
+#undef NL
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index d293d03f63d..2b7c63767ab 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -30,10 +30,14 @@
* Core routines for how the Depsgraph works.
*/
+#include "intern/depsgraph.h" /* own include */
+
#include <string.h>
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
#include "BLI_listbase.h"
extern "C" {
@@ -50,11 +54,15 @@ extern "C" {
}
#include "DEG_depsgraph.h"
-#include "depsgraph.h" /* own include */
-#include "depsnode.h"
-#include "depsnode_operation.h"
-#include "depsnode_component.h"
-#include "depsgraph_intern.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
static DEG_EditorUpdateIDCb deg_editor_update_id_cb = NULL;
static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL;
@@ -66,6 +74,9 @@ Depsgraph::Depsgraph()
layers(0)
{
BLI_spin_init(&lock);
+ id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
+ subgraphs = BLI_gset_ptr_new("Depsgraph subgraphs");
+ entry_tags = BLI_gset_ptr_new("Depsgraph entry_tags");
}
Depsgraph::~Depsgraph()
@@ -73,6 +84,9 @@ Depsgraph::~Depsgraph()
/* Free root node - it won't have been freed yet... */
clear_id_nodes();
clear_subgraph_nodes();
+ BLI_ghash_free(id_hash, NULL, NULL);
+ BLI_gset_free(subgraphs, NULL);
+ BLI_gset_free(entry_tags, NULL);
if (this->root_node != NULL) {
OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode);
}
@@ -235,10 +249,16 @@ DepsNode *Depsgraph::find_node_from_pointer(const PointerRNA *ptr,
/* Node Management ---------------------------- */
+static void id_node_deleter(void *value)
+{
+ IDDepsNode *id_node = reinterpret_cast<IDDepsNode *>(value);
+ OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
+}
+
RootDepsNode *Depsgraph::add_root_node()
{
if (!root_node) {
- DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_ROOT);
+ DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_ROOT);
root_node = (RootDepsNode *)factory->create_node(NULL, "", "Root (Scene)");
}
return root_node;
@@ -267,12 +287,12 @@ TimeSourceDepsNode *Depsgraph::find_time_source(const ID *id) const
SubgraphDepsNode *Depsgraph::add_subgraph_node(const ID *id)
{
- DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_SUBGRAPH);
+ DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_SUBGRAPH);
SubgraphDepsNode *subgraph_node =
(SubgraphDepsNode *)factory->create_node(id, "", id->name + 2);
/* Add to subnodes list. */
- this->subgraphs.insert(subgraph_node);
+ BLI_gset_insert(subgraphs, subgraph_node);
/* if there's an ID associated, add to ID-nodes lookup too */
if (id) {
@@ -289,37 +309,34 @@ SubgraphDepsNode *Depsgraph::add_subgraph_node(const ID *id)
void Depsgraph::remove_subgraph_node(SubgraphDepsNode *subgraph_node)
{
- subgraphs.erase(subgraph_node);
+ BLI_gset_remove(subgraphs, subgraph_node, NULL);
OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode);
}
void Depsgraph::clear_subgraph_nodes()
{
- for (Subgraphs::iterator it = subgraphs.begin();
- it != subgraphs.end();
- ++it)
+ GSET_FOREACH_BEGIN(SubgraphDepsNode *, subgraph_node, subgraphs)
{
- SubgraphDepsNode *subgraph_node = *it;
OBJECT_GUARDED_DELETE(subgraph_node, SubgraphDepsNode);
}
- subgraphs.clear();
+ GSET_FOREACH_END();
+ BLI_gset_clear(subgraphs, NULL);
}
IDDepsNode *Depsgraph::find_id_node(const ID *id) const
{
- IDNodeMap::const_iterator it = this->id_hash.find(id);
- return it != this->id_hash.end() ? it->second : NULL;
+ return reinterpret_cast<IDDepsNode *>(BLI_ghash_lookup(id_hash, id));
}
IDDepsNode *Depsgraph::add_id_node(ID *id, const string &name)
{
IDDepsNode *id_node = find_id_node(id);
if (!id_node) {
- DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_ID_REF);
+ DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_ID_REF);
id_node = (IDDepsNode *)factory->create_node(id, "", name);
id->tag |= LIB_TAG_DOIT;
/* register */
- this->id_hash[id] = id_node;
+ BLI_ghash_insert(id_hash, id, id_node);
}
return id_node;
}
@@ -329,21 +346,14 @@ void Depsgraph::remove_id_node(const ID *id)
IDDepsNode *id_node = find_id_node(id);
if (id_node) {
/* unregister */
- this->id_hash.erase(id);
+ BLI_ghash_remove(id_hash, id, NULL, NULL);
OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
}
}
void Depsgraph::clear_id_nodes()
{
- for (IDNodeMap::const_iterator it = id_hash.begin();
- it != id_hash.end();
- ++it)
- {
- IDDepsNode *id_node = it->second;
- OBJECT_GUARDED_DELETE(id_node, IDDepsNode);
- }
- id_hash.clear();
+ BLI_ghash_clear(id_hash, NULL, id_node_deleter);
}
/* Add new relationship between two nodes. */
@@ -449,33 +459,52 @@ void Depsgraph::add_entry_tag(OperationDepsNode *node)
/* Add to graph-level set of directly modified nodes to start searching from.
* NOTE: this is necessary since we have several thousand nodes to play with...
*/
- this->entry_tags.insert(node);
+ BLI_gset_insert(entry_tags, node);
}
void Depsgraph::clear_all_nodes()
{
clear_id_nodes();
clear_subgraph_nodes();
- id_hash.clear();
+ BLI_ghash_clear(id_hash, NULL, NULL);
if (this->root_node) {
OBJECT_GUARDED_DELETE(this->root_node, RootDepsNode);
root_node = NULL;
}
}
+void deg_editors_id_update(Main *bmain, ID *id)
+{
+ if (deg_editor_update_id_cb != NULL) {
+ deg_editor_update_id_cb(bmain, id);
+ }
+}
+
+void deg_editors_scene_update(Main *bmain, Scene *scene, bool updated)
+{
+ if (deg_editor_update_scene_cb != NULL) {
+ deg_editor_update_scene_cb(bmain, scene, updated);
+ }
+}
+
+} // namespace DEG
+
/* **************** */
/* Public Graph API */
/* Initialize a new Depsgraph */
Depsgraph *DEG_graph_new()
{
- return OBJECT_GUARDED_NEW(Depsgraph);
+ DEG::Depsgraph *deg_depsgraph = OBJECT_GUARDED_NEW(DEG::Depsgraph);
+ return reinterpret_cast<Depsgraph *>(deg_depsgraph);
}
/* Free graph's contents and graph itself */
void DEG_graph_free(Depsgraph *graph)
{
- OBJECT_GUARDED_DELETE(graph, Depsgraph);
+ using DEG::Depsgraph;
+ DEG::Depsgraph *deg_depsgraph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ OBJECT_GUARDED_DELETE(deg_depsgraph, Depsgraph);
}
/* Set callbacks which are being called when depsgraph changes. */
@@ -483,28 +512,14 @@ void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func,
DEG_EditorUpdateSceneCb scene_func,
DEG_EditorUpdateScenePreCb scene_pre_func)
{
- deg_editor_update_id_cb = id_func;
- deg_editor_update_scene_cb = scene_func;
- deg_editor_update_scene_pre_cb = scene_pre_func;
+ DEG::deg_editor_update_id_cb = id_func;
+ DEG::deg_editor_update_scene_cb = scene_func;
+ DEG::deg_editor_update_scene_pre_cb = scene_pre_func;
}
void DEG_editors_update_pre(Main *bmain, Scene *scene, bool time)
{
- if (deg_editor_update_scene_pre_cb != NULL) {
- deg_editor_update_scene_pre_cb(bmain, scene, time);
- }
-}
-
-void deg_editors_id_update(Main *bmain, ID *id)
-{
- if (deg_editor_update_id_cb != NULL) {
- deg_editor_update_id_cb(bmain, id);
- }
-}
-
-void deg_editors_scene_update(Main *bmain, Scene *scene, bool updated)
-{
- if (deg_editor_update_scene_cb != NULL) {
- deg_editor_update_scene_cb(bmain, scene, updated);
+ if (DEG::deg_editor_update_scene_pre_cb != NULL) {
+ DEG::deg_editor_update_scene_pre_cb(bmain, scene, time);
}
}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index 9533fbd10d5..213bb304d73 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -34,19 +34,20 @@
* in the graph.
*/
-#ifndef __DEPSGRAPH_H__
-#define __DEPSGRAPH_H__
+#pragma once
#include "BLI_threads.h" /* for SpinLock */
-#include "depsgraph_types.h"
-
-#include "depsgraph_util_map.h"
-#include "depsgraph_util_set.h"
+#include "intern/depsgraph_types.h"
+struct ID;
+struct GHash;
+struct GSet;
struct PointerRNA;
struct PropertyRNA;
+namespace DEG {
+
struct DepsNode;
struct RootDepsNode;
struct TimeSourceDepsNode;
@@ -94,9 +95,6 @@ struct DepsRelation {
/* Dependency Graph object */
struct Depsgraph {
- typedef unordered_map<const ID *, IDDepsNode *> IDNodeMap;
- typedef unordered_set<SubgraphDepsNode *> Subgraphs;
- typedef unordered_set<OperationDepsNode *> EntryTags;
typedef vector<OperationDepsNode *> OperationNodes;
Depsgraph();
@@ -163,13 +161,13 @@ struct Depsgraph {
/* <ID : IDDepsNode> mapping from ID blocks to nodes representing these blocks
* (for quick lookups). */
- IDNodeMap id_hash;
+ GHash *id_hash;
/* "root" node - the one where all evaluation enters from. */
RootDepsNode *root_node;
/* Subgraphs referenced in tree. */
- Subgraphs subgraphs;
+ GSet *subgraphs;
/* Indicates whether relations needs to be updated. */
bool need_update;
@@ -177,7 +175,7 @@ struct Depsgraph {
/* Quick-Access Temp Data ............. */
/* Nodes which have been tagged as "directly modified". */
- EntryTags entry_tags;
+ GSet *entry_tags;
/* Convenience Data ................... */
@@ -198,27 +196,4 @@ struct Depsgraph {
// XXX: additional stuff like eval contexts, mempools for allocating nodes from, etc.
};
-/**
- * Helper macros for iterating over set of relationship links
- * incident on each node.
- *
- * \note it is safe to perform removal operations here...
- *
- * relations_set[in]: (DepsNode::Relations) set of relationships (in/out links)
- * relation[out]: (DepsRelation *) identifier where DepsRelation that we're
- * currently accessing comes up
- */
-#define DEPSNODE_RELATIONS_ITER_BEGIN(relations_set_, relation_) \
- { \
- OperationDepsNode::Relations::const_iterator __rel_iter = relations_set_.begin(); \
- while (__rel_iter != relations_set_.end()) { \
- DepsRelation *relation_ = *__rel_iter; \
- ++__rel_iter; \
-
- /* ... code for iterator body can be written here ... */
-
-#define DEPSNODE_RELATIONS_ITER_END \
- } \
- } ((void)0)
-
-#endif /* __DEPSGRAPH_H__ */
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 82f312c2171..b1271c39851 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -30,135 +30,128 @@
* Methods for constructing depsgraph.
*/
-#include <stack>
-
#include "MEM_guardedalloc.h"
extern "C" {
-#include "BLI_blenlib.h"
-#include "BLI_string.h"
-#include "BLI_utildefines.h"
-
-#include "DNA_action_types.h"
-#include "DNA_anim_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_effect_types.h"
-#include "DNA_group_types.h"
-#include "DNA_key_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meta_types.h"
-#include "DNA_node_types.h"
#include "DNA_object_types.h"
-#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
-#include "DNA_texture_types.h"
-#include "DNA_world_types.h"
-
-#include "BKE_action.h"
-#include "BKE_armature.h"
-#include "BKE_animsys.h"
-#include "BKE_constraint.h"
-#include "BKE_curve.h"
-#include "BKE_effect.h"
-#include "BKE_fcurve.h"
-#include "BKE_group.h"
-#include "BKE_key.h"
-#include "BKE_library.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+
#include "BKE_main.h"
-#include "BKE_material.h"
-#include "BKE_mball.h"
-#include "BKE_modifier.h"
-#include "BKE_node.h"
-#include "BKE_object.h"
-#include "BKE_rigidbody.h"
-#include "BKE_sound.h"
-#include "BKE_texture.h"
-#include "BKE_tracking.h"
-#include "BKE_world.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_build.h"
-#include "RNA_access.h"
-#include "RNA_types.h"
} /* extern "C" */
-#include "depsnode.h"
-#include "depsnode_component.h"
-#include "depsgraph_debug.h"
-#include "depsnode_operation.h"
-#include "depsgraph_types.h"
-#include "depsgraph_build.h"
-#include "depsgraph_intern.h"
+#include "builder/deg_builder.h"
+#include "builder/deg_builder_cycle.h"
+#include "builder/deg_builder_nodes.h"
+#include "builder/deg_builder_relations.h"
+#include "builder/deg_builder_transitive.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "intern/depsgraph_types.h"
+#include "intern/depsgraph_intern.h"
-#include "depsgraph_util_cycle.h"
-#include "depsgraph_util_transitive.h"
+#include "util/deg_util_foreach.h"
/* ****************** */
/* External Build API */
-static eDepsNode_Type deg_build_scene_component_type(eDepsSceneComponentType component)
+static DEG::eDepsNode_Type deg_build_scene_component_type(
+ eDepsSceneComponentType component)
{
switch (component) {
- case DEG_SCENE_COMP_PARAMETERS: return DEPSNODE_TYPE_PARAMETERS;
- case DEG_SCENE_COMP_ANIMATION: return DEPSNODE_TYPE_ANIMATION;
- case DEG_SCENE_COMP_SEQUENCER: return DEPSNODE_TYPE_SEQUENCER;
+ case DEG_SCENE_COMP_PARAMETERS: return DEG::DEPSNODE_TYPE_PARAMETERS;
+ case DEG_SCENE_COMP_ANIMATION: return DEG::DEPSNODE_TYPE_ANIMATION;
+ case DEG_SCENE_COMP_SEQUENCER: return DEG::DEPSNODE_TYPE_SEQUENCER;
}
- return DEPSNODE_TYPE_UNDEFINED;
+ return DEG::DEPSNODE_TYPE_UNDEFINED;
}
-static eDepsNode_Type deg_build_object_component_type(eDepsObjectComponentType component)
+static DEG::eDepsNode_Type deg_build_object_component_type(
+ eDepsObjectComponentType component)
{
switch (component) {
- case DEG_OB_COMP_PARAMETERS: return DEPSNODE_TYPE_PARAMETERS;
- case DEG_OB_COMP_PROXY: return DEPSNODE_TYPE_PROXY;
- case DEG_OB_COMP_ANIMATION: return DEPSNODE_TYPE_ANIMATION;
- case DEG_OB_COMP_TRANSFORM: return DEPSNODE_TYPE_TRANSFORM;
- case DEG_OB_COMP_GEOMETRY: return DEPSNODE_TYPE_GEOMETRY;
- case DEG_OB_COMP_EVAL_POSE: return DEPSNODE_TYPE_EVAL_POSE;
- case DEG_OB_COMP_BONE: return DEPSNODE_TYPE_BONE;
- case DEG_OB_COMP_EVAL_PARTICLES: return DEPSNODE_TYPE_EVAL_PARTICLES;
- case DEG_OB_COMP_SHADING: return DEPSNODE_TYPE_SHADING;
+ case DEG_OB_COMP_PARAMETERS: return DEG::DEPSNODE_TYPE_PARAMETERS;
+ case DEG_OB_COMP_PROXY: return DEG::DEPSNODE_TYPE_PROXY;
+ case DEG_OB_COMP_ANIMATION: return DEG::DEPSNODE_TYPE_ANIMATION;
+ case DEG_OB_COMP_TRANSFORM: return DEG::DEPSNODE_TYPE_TRANSFORM;
+ case DEG_OB_COMP_GEOMETRY: return DEG::DEPSNODE_TYPE_GEOMETRY;
+ case DEG_OB_COMP_EVAL_POSE: return DEG::DEPSNODE_TYPE_EVAL_POSE;
+ case DEG_OB_COMP_BONE: return DEG::DEPSNODE_TYPE_BONE;
+ case DEG_OB_COMP_EVAL_PARTICLES: return DEG::DEPSNODE_TYPE_EVAL_PARTICLES;
+ case DEG_OB_COMP_SHADING: return DEG::DEPSNODE_TYPE_SHADING;
}
- return DEPSNODE_TYPE_UNDEFINED;
+ return DEG::DEPSNODE_TYPE_UNDEFINED;
}
-void DEG_add_scene_relation(DepsNodeHandle *handle, struct Scene *scene, eDepsSceneComponentType component, const char *description)
+static DEG::DepsNodeHandle *get_handle(DepsNodeHandle *handle)
{
- eDepsNode_Type type = deg_build_scene_component_type(component);
- ComponentKey comp_key(&scene->id, type);
- handle->builder->add_node_handle_relation(comp_key, handle, DEPSREL_TYPE_GEOMETRY_EVAL, description);
+ return reinterpret_cast<DEG::DepsNodeHandle *>(handle);
}
-void DEG_add_object_relation(DepsNodeHandle *handle, struct Object *ob, eDepsObjectComponentType component, const char *description)
+void DEG_add_scene_relation(DepsNodeHandle *handle,
+ Scene *scene,
+ eDepsSceneComponentType component,
+ const char *description)
{
- eDepsNode_Type type = deg_build_object_component_type(component);
- ComponentKey comp_key(&ob->id, type);
- handle->builder->add_node_handle_relation(comp_key, handle, DEPSREL_TYPE_GEOMETRY_EVAL, description);
+ DEG::eDepsNode_Type type = deg_build_scene_component_type(component);
+ DEG::ComponentKey comp_key(&scene->id, type);
+ DEG::DepsNodeHandle *deg_handle = get_handle(handle);
+ deg_handle->builder->add_node_handle_relation(comp_key,
+ deg_handle,
+ DEG::DEPSREL_TYPE_GEOMETRY_EVAL,
+ description);
}
-void DEG_add_bone_relation(DepsNodeHandle *handle, struct Object *ob, const char *bone_name, eDepsObjectComponentType component, const char *description)
+void DEG_add_object_relation(DepsNodeHandle *handle,
+ Object *ob,
+ eDepsObjectComponentType component,
+ const char *description)
{
- eDepsNode_Type type = deg_build_object_component_type(component);
- ComponentKey comp_key(&ob->id, type, bone_name);
+ DEG::eDepsNode_Type type = deg_build_object_component_type(component);
+ DEG::ComponentKey comp_key(&ob->id, type);
+ DEG::DepsNodeHandle *deg_handle = get_handle(handle);
+ deg_handle->builder->add_node_handle_relation(comp_key,
+ deg_handle,
+ DEG::DEPSREL_TYPE_GEOMETRY_EVAL,
+ description);
+}
- // XXX: "Geometry Eval" might not always be true, but this only gets called from modifier building now
- handle->builder->add_node_handle_relation(comp_key, handle, DEPSREL_TYPE_GEOMETRY_EVAL, description);
+void DEG_add_bone_relation(DepsNodeHandle *handle,
+ Object *ob,
+ const char *bone_name,
+ eDepsObjectComponentType component,
+ const char *description)
+{
+ DEG::eDepsNode_Type type = deg_build_object_component_type(component);
+ DEG::ComponentKey comp_key(&ob->id, type, bone_name);
+ DEG::DepsNodeHandle *deg_handle = get_handle(handle);
+ /* XXX: "Geometry Eval" might not always be true, but this only gets called
+ * from modifier building now.
+ */
+ deg_handle->builder->add_node_handle_relation(comp_key,
+ deg_handle,
+ DEG::DEPSREL_TYPE_GEOMETRY_EVAL,
+ description);
}
void DEG_add_special_eval_flag(Depsgraph *graph, ID *id, short flag)
{
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
if (graph == NULL) {
BLI_assert(!"Graph should always be valid");
return;
}
- IDDepsNode *id_node = graph->find_id_node(id);
+ DEG::IDDepsNode *id_node = deg_graph->find_id_node(id);
if (id_node == NULL) {
BLI_assert(!"ID should always be valid");
return;
@@ -166,110 +159,21 @@ void DEG_add_special_eval_flag(Depsgraph *graph, ID *id, short flag)
id_node->eval_flags |= flag;
}
-/* ********************** */
-/* Utilities for Builders */
-
-/* Get unique identifier for FCurves and Drivers */
-string deg_fcurve_id_name(const FCurve *fcu)
-{
- char index_buf[32];
- sprintf(index_buf, "[%d]", fcu->array_index);
-
- return string(fcu->rna_path) + index_buf;
-}
-
-static void deg_graph_build_finalize(Depsgraph *graph)
-{
- std::stack<OperationDepsNode *> stack;
-
- for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
- it_op != graph->operations.end();
- ++it_op)
- {
- OperationDepsNode *node = *it_op;
- node->done = 0;
- node->num_links_pending = 0;
- for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin();
- it_rel != node->inlinks.end();
- ++it_rel)
- {
- DepsRelation *rel = *it_rel;
- if ((rel->from->type == DEPSNODE_TYPE_OPERATION) &&
- (rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
- {
- ++node->num_links_pending;
- }
- }
- if (node->num_links_pending == 0) {
- stack.push(node);
- }
- IDDepsNode *id_node = node->owner->owner;
- id_node->id->tag |= LIB_TAG_DOIT;
- }
-
- while (!stack.empty()) {
- OperationDepsNode *node = stack.top();
- if (node->done == 0 && node->outlinks.size() != 0) {
- for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
- it_rel != node->outlinks.end();
- ++it_rel)
- {
- DepsRelation *rel = *it_rel;
- if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
- OperationDepsNode *to = (OperationDepsNode *)rel->to;
- if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
- BLI_assert(to->num_links_pending > 0);
- --to->num_links_pending;
- }
- if (to->num_links_pending == 0) {
- stack.push(to);
- }
- }
- }
- node->done = 1;
- }
- else {
- stack.pop();
- IDDepsNode *id_node = node->owner->owner;
- for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
- it_rel != node->outlinks.end();
- ++it_rel)
- {
- DepsRelation *rel = *it_rel;
- if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
- OperationDepsNode *to = (OperationDepsNode *)rel->to;
- IDDepsNode *id_to = to->owner->owner;
- id_node->layers |= id_to->layers;
- }
- }
- }
- }
-
- /* Re-tag IDs for update if it was tagged before the relations update tag. */
- for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin();
- it != graph->id_hash.end();
- ++it)
- {
- IDDepsNode *id_node = it->second;
- ID *id = id_node->id;
- if (id->tag & LIB_TAG_ID_RECALC_ALL &&
- id->tag & LIB_TAG_DOIT)
- {
- id_node->tag_update(graph);
- id->tag &= ~LIB_TAG_DOIT;
- }
- }
-}
-
/* ******************** */
/* Graph Building API's */
-/* Build depsgraph for the given scene, and dump results in given graph container */
-// XXX: assume that this is called from outside, given the current scene as the "main" scene
+/* Build depsgraph for the given scene, and dump results in given
+ * graph container.
+ */
+/* XXX: assume that this is called from outside, given the current scene as
+ * the "main" scene.
+ */
void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
{
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+
/* 1) Generate all the nodes in the graph first */
- DepsgraphNodeBuilder node_builder(bmain, graph);
+ DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph);
/* create root node for scene first
* - this way it should be the first in the graph,
* reflecting its role as the entrypoint
@@ -277,29 +181,40 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
node_builder.add_root_node();
node_builder.build_scene(bmain, scene);
- /* 2) Hook up relationships between operations - to determine evaluation order */
- DepsgraphRelationBuilder relation_builder(graph);
- /* hook scene up to the root node as entrypoint to graph */
+ /* 2) Hook up relationships between operations - to determine evaluation
+ * order.
+ */
+ DEG::DepsgraphRelationBuilder relation_builder(deg_graph);
+ /* Hook scene up to the root node as entrypoint to graph. */
/* XXX what does this relation actually mean?
- * it doesnt add any operations anyway and is not clear what part of the scene is to be connected.
+ * it doesnt add any operations anyway and is not clear what part of the
+ * scene is to be connected.
*/
- //relation_builder.add_relation(RootKey(), IDKey(scene), DEPSREL_TYPE_ROOT_TO_ACTIVE, "Root to Active Scene");
+#if 0
+ relation_builder.add_relation(RootKey(),
+ IDKey(scene),
+ DEPSREL_TYPE_ROOT_TO_ACTIVE,
+ "Root to Active Scene");
+#endif
relation_builder.build_scene(bmain, scene);
/* Detect and solve cycles. */
- deg_graph_detect_cycles(graph);
+ DEG::deg_graph_detect_cycles(deg_graph);
- /* 3) Simplify the graph by removing redundant relations (to optimise traversal later) */
- // TODO: it would be useful to have an option to disable this in cases where it is causing trouble
+ /* 3) Simplify the graph by removing redundant relations (to optimize
+ * traversal later). */
+ /* TODO: it would be useful to have an option to disable this in cases where
+ * it is causing trouble.
+ */
if (G.debug_value == 799) {
- deg_graph_transitive_reduction(graph);
+ DEG::deg_graph_transitive_reduction(deg_graph);
}
/* 4) Flush visibility layer and re-schedule nodes for update. */
- deg_graph_build_finalize(graph);
+ DEG::deg_graph_build_finalize(deg_graph);
#if 0
- if (!DEG_debug_consistency_check(graph)) {
+ if (!DEG_debug_consistency_check(deg_graph)) {
printf("Consistency validation failed, ABORTING!\n");
abort();
}
@@ -309,7 +224,8 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
/* Tag graph relations for update. */
void DEG_graph_tag_relations_update(Depsgraph *graph)
{
- graph->need_update = true;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ deg_graph->need_update = true;
}
/* Tag all relations for update. */
@@ -337,7 +253,7 @@ void DEG_scene_relations_update(Main *bmain, Scene *scene)
return;
}
- Depsgraph *graph = scene->depsgraph;
+ DEG::Depsgraph *graph = reinterpret_cast<DEG::Depsgraph *>(scene->depsgraph);
if (!graph->need_update) {
/* Graph is up to date, nothing to do. */
return;
@@ -346,10 +262,12 @@ void DEG_scene_relations_update(Main *bmain, Scene *scene)
/* Clear all previous nodes and operations. */
graph->clear_all_nodes();
graph->operations.clear();
- graph->entry_tags.clear();
+ BLI_gset_clear(graph->entry_tags, NULL);
/* Build new nodes and relations. */
- DEG_graph_build_from_scene(graph, bmain, scene);
+ DEG_graph_build_from_scene(reinterpret_cast< ::Depsgraph * >(graph),
+ bmain,
+ scene);
graph->need_update = false;
}
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index efb3e330857..d3b48930779 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -30,956 +30,39 @@
* Implementation of tools for debugging the depsgraph
*/
-//#include <stdlib.h>
-#include <string.h>
-
-extern "C" {
#include "BLI_utildefines.h"
-#include "BLI_listbase.h"
#include "BLI_ghash.h"
-#include "BLI_string.h"
+extern "C" {
#include "DNA_scene_types.h"
-#include "DNA_userdef_types.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
#include "DEG_depsgraph_build.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
} /* extern "C" */
-#include "depsgraph_debug.h"
-#include "depsnode.h"
-#include "depsnode_component.h"
-#include "depsnode_operation.h"
-#include "depsgraph_intern.h"
-
-/* ****************** */
-/* Graphviz Debugging */
-
-#define NL "\r\n"
-
-/* Only one should be enabled, defines whether graphviz nodes
- * get colored by individual types or classes.
- */
-#define COLOR_SCHEME_NODE_CLASS 1
-//#define COLOR_SCHEME_NODE_TYPE 2
-
-static const char *deg_debug_graphviz_fontname = "helvetica";
-static float deg_debug_graphviz_graph_label_size = 20.0f;
-static float deg_debug_graphviz_node_label_size = 14.0f;
-static const int deg_debug_max_colors = 12;
-#if 0
-static const char *deg_debug_colors_dark[] = {
- "#6e8997", "#144f77", "#76945b",
- "#216a1d", "#a76665", "#971112",
- "#a87f49", "#0a9540", "#86768e",
- "#462866", "#a9a965", "#753b1a",
-};
-#endif
-#ifdef COLOR_SCHEME_NODE_TYPE
-static const char *deg_debug_colors[] = {
- "#a6cee3", "#1f78b4", "#b2df8a",
- "#33a02c", "#fb9a99", "#e31a1c",
- "#fdbf6f", "#ff7f00", "#cab2d6",
- "#6a3d9a", "#ffff99", "#b15928",
-};
-#endif
-static const char *deg_debug_colors_light[] = {
- "#8dd3c7", "#ffffb3", "#bebada",
- "#fb8072", "#80b1d3", "#fdb462",
- "#b3de69", "#fccde5", "#d9d9d9",
- "#bc80bd", "#ccebc5", "#ffed6f",
-};
-
-#ifdef COLOR_SCHEME_NODE_TYPE
-static const int deg_debug_node_type_color_map[][2] = {
- {DEPSNODE_TYPE_ROOT, 0},
- {DEPSNODE_TYPE_TIMESOURCE, 1},
- {DEPSNODE_TYPE_ID_REF, 2},
- {DEPSNODE_TYPE_SUBGRAPH, 3},
-
- /* Outer Types */
- {DEPSNODE_TYPE_PARAMETERS, 4},
- {DEPSNODE_TYPE_PROXY, 5},
- {DEPSNODE_TYPE_ANIMATION, 6},
- {DEPSNODE_TYPE_TRANSFORM, 7},
- {DEPSNODE_TYPE_GEOMETRY, 8},
- {DEPSNODE_TYPE_SEQUENCER, 9},
- {DEPSNODE_TYPE_SHADING, 10},
- {-1, 0}
-};
-#endif
-
-#if 0 /* unused */
-static const int deg_debug_relation_type_color_map[][2] = {
- {DEPSREL_TYPE_STANDARD, 0},
- {DEPSREL_TYPE_ROOT_TO_ACTIVE, 1},
- {DEPSREL_TYPE_DATABLOCK, 2},
- {DEPSREL_TYPE_TIME, 3},
- {DEPSREL_TYPE_COMPONENT_ORDER, 4},
- {DEPSREL_TYPE_OPERATION, 5},
- {DEPSREL_TYPE_DRIVER, 6},
- {DEPSREL_TYPE_DRIVER_TARGET, 7},
- {DEPSREL_TYPE_TRANSFORM, 8},
- {DEPSREL_TYPE_GEOMETRY_EVAL, 9},
- {DEPSREL_TYPE_UPDATE, 10},
- {DEPSREL_TYPE_UPDATE_UI, 11},
- {-1, 0}
-};
-#endif
-
-static int deg_debug_node_color_index(const DepsNode *node)
-{
-#ifdef COLOR_SCHEME_NODE_CLASS
- /* Some special types. */
- switch (node->type) {
- case DEPSNODE_TYPE_ID_REF:
- return 5;
- case DEPSNODE_TYPE_OPERATION:
- {
- OperationDepsNode *op_node = (OperationDepsNode *)node;
- if (op_node->is_noop())
- return 8;
- break;
- }
-
- default:
- break;
- }
- /* Do others based on class. */
- switch (node->tclass) {
- case DEPSNODE_CLASS_OPERATION:
- return 4;
- case DEPSNODE_CLASS_COMPONENT:
- return 1;
- default:
- return 9;
- }
-#endif
-
-#ifdef COLOR_SCHEME_NODE_TYPE
- const int (*pair)[2];
- for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
- if ((*pair)[0] == node->type) {
- return (*pair)[1];
- }
- }
- return -1;
-#endif
-}
-
-struct DebugContext {
- FILE *file;
- bool show_tags;
- bool show_eval_priority;
-};
-
-static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) ATTR_PRINTF_FORMAT(2, 3);
-static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- vfprintf(ctx.file, fmt, args);
- va_end(args);
-}
-
-static void deg_debug_graphviz_legend_color(const DebugContext &ctx,
- const char *name,
- const char *color)
-{
- deg_debug_fprintf(ctx, "<TR>");
- deg_debug_fprintf(ctx, "<TD>%s</TD>", name);
- deg_debug_fprintf(ctx, "<TD BGCOLOR=\"%s\"></TD>", color);
- deg_debug_fprintf(ctx, "</TR>" NL);
-}
-
-#if 0
-static void deg_debug_graphviz_legend_line(const DebugContext &ctx,
- const char *name,
- const char *color,
- const char *style)
-{
- /* XXX TODO */
- deg_debug_fprintf(ctx, "" NL);
-}
-
-static void deg_debug_graphviz_legend_cluster(const DebugContext &ctx,
- const char *name,
- const char *color,
- const char *style)
-{
- deg_debug_fprintf(ctx, "<TR>");
- deg_debug_fprintf(ctx, "<TD>%s</TD>", name);
- deg_debug_fprintf(ctx, "<TD CELLPADDING=\"4\"><TABLE BORDER=\"1\" CELLBORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">");
- deg_debug_fprintf(ctx, "<TR><TD BGCOLOR=\"%s\"></TD></TR>", color);
- deg_debug_fprintf(ctx, "</TABLE></TD>");
- deg_debug_fprintf(ctx, "</TR>" NL);
-}
-#endif
-
-static void deg_debug_graphviz_legend(const DebugContext &ctx)
-{
- deg_debug_fprintf(ctx, "{" NL);
- deg_debug_fprintf(ctx, "rank = sink;" NL);
- deg_debug_fprintf(ctx, "Legend [shape=none, margin=0, label=<" NL);
- deg_debug_fprintf(ctx, " <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">" NL);
- deg_debug_fprintf(ctx, "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>" NL);
-
-#ifdef COLOR_SCHEME_NODE_CLASS
- const char **colors = deg_debug_colors_light;
- deg_debug_graphviz_legend_color(ctx, "Operation", colors[4]);
- deg_debug_graphviz_legend_color(ctx, "Component", colors[1]);
- deg_debug_graphviz_legend_color(ctx, "ID Node", colors[5]);
- deg_debug_graphviz_legend_color(ctx, "NOOP", colors[8]);
-#endif
-
-#ifdef COLOR_SCHEME_NODE_TYPE
- const int (*pair)[2];
- for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
- DepsNodeFactory *nti = DEG_get_node_factory((eDepsNode_Type)(*pair)[0]);
- deg_debug_graphviz_legend_color(ctx,
- nti->tname().c_str(),
- deg_debug_colors_light[(*pair)[1] % deg_debug_max_colors]);
- }
-#endif
-
- deg_debug_fprintf(ctx, "</TABLE>" NL);
- deg_debug_fprintf(ctx, ">" NL);
- deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
- deg_debug_fprintf(ctx, "];" NL);
- deg_debug_fprintf(ctx, "}" NL);
-}
-
-#if 0 /* unused */
-static int deg_debug_relation_type_color_index(eDepsRelation_Type type)
-{
- const int (*pair)[2];
- for (pair = deg_debug_relation_type_color_map; (*pair)[0] >= 0; ++pair) {
- if ((*pair)[0] == type) {
- return (*pair)[1];
- }
- }
- return -1;
-}
-#endif
-
-static void deg_debug_graphviz_node_color(const DebugContext &ctx,
- const DepsNode *node)
-{
- const char *color_default = "black";
- const char *color_modified = "orangered4";
- const char *color_update = "dodgerblue3";
- const char *color = color_default;
- if (ctx.show_tags) {
- if (node->tclass == DEPSNODE_CLASS_OPERATION) {
- OperationDepsNode *op_node = (OperationDepsNode *)node;
- if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
- color = color_modified;
- }
- else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
- color = color_update;
- }
- }
- }
- deg_debug_fprintf(ctx, "\"%s\"", color);
-}
-
-static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx,
- const DepsNode *node)
-{
- float penwidth_default = 1.0f;
- float penwidth_modified = 4.0f;
- float penwidth_update = 4.0f;
- float penwidth = penwidth_default;
- if (ctx.show_tags) {
- if (node->tclass == DEPSNODE_CLASS_OPERATION) {
- OperationDepsNode *op_node = (OperationDepsNode *)node;
- if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
- penwidth = penwidth_modified;
- }
- else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
- penwidth = penwidth_update;
- }
- }
- }
- deg_debug_fprintf(ctx, "\"%f\"", penwidth);
-}
-
-static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx,
- const DepsNode *node)
-{
- const char *defaultcolor = "gainsboro";
- int color_index = deg_debug_node_color_index(node);
- const char *fillcolor = color_index < 0 ? defaultcolor : deg_debug_colors_light[color_index % deg_debug_max_colors];
- deg_debug_fprintf(ctx, "\"%s\"", fillcolor);
-}
-
-#if 0 /* implementation using stripes, a bit too noisy ... */
-static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx,
- const DepsNode *node)
-{
- const char *defaultcolor = "gainsboro";
- const char *color_needs_update = "orange";
- const int num_stripes = 10;
- int color_index = deg_debug_node_color_index(node);
- const char *base_color = color_index < 0 ? defaultcolor : deg_debug_colors_light[color_index % deg_debug_max_colors];
- if (ctx.show_tags &&
- (node->flag & (DEPSNODE_FLAG_DIRECTLY_MODIFIED | DEPSNODE_FLAG_NEEDS_UPDATE)))
- {
- deg_debug_fprintf(ctx, "\"");
- for (int i = 0; i < num_stripes; ++i) {
- if (i > 0) {
- deg_debug_fprintf(ctx, ":");
- }
- deg_debug_fprintf(ctx, "%s:%s", base_color, color_needs_update);
- }
- deg_debug_fprintf(ctx, "\"");
- }
- else {
- deg_debug_fprintf(ctx, "\"%s\"", base_color);
- }
-}
-#endif
-
-static void deg_debug_graphviz_relation_color(const DebugContext &ctx,
- const DepsRelation *rel)
-{
- const char *color_default = "black";
- const char *color_error = "red4";
- const char *color = color_default;
-#if 0 /* disabled for now, edge colors are hardly distinguishable */
- int color = deg_debug_relation_type_color_index(rel->type);
- if (color < 0) {
- deg_debug_fprintf(ctx, "%s", defaultcolor);
- }
- else {
- deg_debug_fprintf(ctx, "\"%s\"", deg_debug_colors_dark[color % deg_debug_max_colors]);
- }
-#else
- if (rel->flag & DEPSREL_FLAG_CYCLIC)
- color = color_error;
-
- deg_debug_fprintf(ctx, "%s", color);
-#endif
-}
-
-static void deg_debug_graphviz_node_style(const DebugContext &ctx, const DepsNode *node)
-{
- const char *base_style = "filled"; /* default style */
- if (ctx.show_tags) {
- if (node->tclass == DEPSNODE_CLASS_OPERATION) {
- OperationDepsNode *op_node = (OperationDepsNode *)node;
- if (op_node->flag & (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE)) {
- base_style = "striped";
- }
- }
- }
- switch (node->tclass) {
- case DEPSNODE_CLASS_GENERIC:
- deg_debug_fprintf(ctx, "\"%s\"", base_style);
- break;
- case DEPSNODE_CLASS_COMPONENT:
- deg_debug_fprintf(ctx, "\"%s\"", base_style);
- break;
- case DEPSNODE_CLASS_OPERATION:
- deg_debug_fprintf(ctx, "\"%s,rounded\"", base_style);
- break;
- }
-}
-
-static void deg_debug_graphviz_node_single(const DebugContext &ctx,
- const DepsNode *node)
-{
- const char *shape = "box";
- string name = node->identifier();
- float priority = -1.0f;
- if (node->type == DEPSNODE_TYPE_ID_REF) {
- IDDepsNode *id_node = (IDDepsNode *)node;
- char buf[256];
- BLI_snprintf(buf, sizeof(buf), " (Layers: %d)", id_node->layers);
- name += buf;
- }
- if (ctx.show_eval_priority && node->tclass == DEPSNODE_CLASS_OPERATION) {
- priority = ((OperationDepsNode *)node)->eval_priority;
- }
- deg_debug_fprintf(ctx, "// %s\n", name.c_str());
- deg_debug_fprintf(ctx, "\"node_%p\"", node);
- deg_debug_fprintf(ctx, "[");
-// deg_debug_fprintf(ctx, "label=<<B>%s</B>>", name);
- if (priority >= 0.0f) {
- deg_debug_fprintf(ctx, "label=<%s<BR/>(<I>%.2f</I>)>",
- name.c_str(),
- priority);
- }
- else {
- deg_debug_fprintf(ctx, "label=<%s>", name.c_str());
- }
- deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
- deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_node_label_size);
- deg_debug_fprintf(ctx, ",shape=%s", shape);
- deg_debug_fprintf(ctx, ",style="); deg_debug_graphviz_node_style(ctx, node);
- deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_node_color(ctx, node);
- deg_debug_fprintf(ctx, ",fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node);
- deg_debug_fprintf(ctx, ",penwidth="); deg_debug_graphviz_node_penwidth(ctx, node);
- deg_debug_fprintf(ctx, "];" NL);
- deg_debug_fprintf(ctx, NL);
-}
-
-static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx,
- const DepsNode *node)
-{
- string name = node->identifier().c_str();
- if (node->type == DEPSNODE_TYPE_ID_REF) {
- IDDepsNode *id_node = (IDDepsNode *)node;
- char buf[256];
- BLI_snprintf(buf, sizeof(buf), " (Layers: %d)", id_node->layers);
- name += buf;
- }
- deg_debug_fprintf(ctx, "// %s\n", name.c_str());
- deg_debug_fprintf(ctx, "subgraph \"cluster_%p\" {" NL, node);
-// deg_debug_fprintf(ctx, "label=<<B>%s</B>>;" NL, name);
- deg_debug_fprintf(ctx, "label=<%s>;" NL, name.c_str());
- deg_debug_fprintf(ctx, "fontname=\"%s\";" NL, deg_debug_graphviz_fontname);
- deg_debug_fprintf(ctx, "fontsize=%f;" NL, deg_debug_graphviz_node_label_size);
- deg_debug_fprintf(ctx, "margin=\"%d\";" NL, 16);
- deg_debug_fprintf(ctx, "style="); deg_debug_graphviz_node_style(ctx, node); deg_debug_fprintf(ctx, ";" NL);
- deg_debug_fprintf(ctx, "color="); deg_debug_graphviz_node_color(ctx, node); deg_debug_fprintf(ctx, ";" NL);
- deg_debug_fprintf(ctx, "fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node); deg_debug_fprintf(ctx, ";" NL);
- deg_debug_fprintf(ctx, "penwidth="); deg_debug_graphviz_node_penwidth(ctx, node); deg_debug_fprintf(ctx, ";" NL);
- /* dummy node, so we can add edges between clusters */
- deg_debug_fprintf(ctx, "\"node_%p\"", node);
- deg_debug_fprintf(ctx, "[");
- deg_debug_fprintf(ctx, "shape=%s", "point");
- deg_debug_fprintf(ctx, ",style=%s", "invis");
- deg_debug_fprintf(ctx, "];" NL);
- deg_debug_fprintf(ctx, NL);
-}
-
-static void deg_debug_graphviz_node_cluster_end(const DebugContext &ctx)
-{
- deg_debug_fprintf(ctx, "}" NL);
- deg_debug_fprintf(ctx, NL);
-}
-
-static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
- const Depsgraph *graph);
-static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
- const Depsgraph *graph);
-
-static void deg_debug_graphviz_node(const DebugContext &ctx,
- const DepsNode *node)
-{
- switch (node->type) {
- case DEPSNODE_TYPE_ID_REF:
- {
- const IDDepsNode *id_node = (const IDDepsNode *)node;
- if (id_node->components.empty()) {
- deg_debug_graphviz_node_single(ctx, node);
- }
- else {
- deg_debug_graphviz_node_cluster_begin(ctx, node);
- for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin();
- it != id_node->components.end();
- ++it)
- {
- const ComponentDepsNode *comp = it->second;
- deg_debug_graphviz_node(ctx, comp);
- }
- deg_debug_graphviz_node_cluster_end(ctx);
- }
- break;
- }
- case DEPSNODE_TYPE_SUBGRAPH:
- {
- SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
- if (sub_node->graph) {
- deg_debug_graphviz_node_cluster_begin(ctx, node);
- deg_debug_graphviz_graph_nodes(ctx, sub_node->graph);
- deg_debug_graphviz_node_cluster_end(ctx);
- }
- else {
- deg_debug_graphviz_node_single(ctx, node);
- }
- break;
- }
- case DEPSNODE_TYPE_PARAMETERS:
- case DEPSNODE_TYPE_ANIMATION:
- case DEPSNODE_TYPE_TRANSFORM:
- case DEPSNODE_TYPE_PROXY:
- case DEPSNODE_TYPE_GEOMETRY:
- case DEPSNODE_TYPE_SEQUENCER:
- case DEPSNODE_TYPE_EVAL_POSE:
- case DEPSNODE_TYPE_BONE:
- case DEPSNODE_TYPE_SHADING:
- case DEPSNODE_TYPE_EVAL_PARTICLES:
- {
- ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
- if (!comp_node->operations.empty()) {
- deg_debug_graphviz_node_cluster_begin(ctx, node);
- for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin();
- it != comp_node->operations.end();
- ++it)
- {
- const DepsNode *op_node = it->second;
- deg_debug_graphviz_node(ctx, op_node);
- }
- deg_debug_graphviz_node_cluster_end(ctx);
- }
- else {
- deg_debug_graphviz_node_single(ctx, node);
- }
- break;
- }
- default:
- deg_debug_graphviz_node_single(ctx, node);
- break;
- }
-}
-
-static bool deg_debug_graphviz_is_cluster(const DepsNode *node)
-{
- switch (node->type) {
- case DEPSNODE_TYPE_ID_REF:
- {
- const IDDepsNode *id_node = (const IDDepsNode *)node;
- return !id_node->components.empty();
- }
- case DEPSNODE_TYPE_SUBGRAPH:
- {
- SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
- return sub_node->graph != NULL;
- }
- case DEPSNODE_TYPE_PARAMETERS:
- case DEPSNODE_TYPE_ANIMATION:
- case DEPSNODE_TYPE_TRANSFORM:
- case DEPSNODE_TYPE_PROXY:
- case DEPSNODE_TYPE_GEOMETRY:
- case DEPSNODE_TYPE_SEQUENCER:
- case DEPSNODE_TYPE_EVAL_POSE:
- case DEPSNODE_TYPE_BONE:
- {
- ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
- return !comp_node->operations.empty();
- }
- default:
- return false;
- }
-}
-
-static bool deg_debug_graphviz_is_owner(const DepsNode *node,
- const DepsNode *other)
-{
- switch (node->tclass) {
- case DEPSNODE_CLASS_COMPONENT:
- {
- ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
- if (comp_node->owner == other)
- return true;
- break;
- }
- case DEPSNODE_CLASS_OPERATION:
- {
- OperationDepsNode *op_node = (OperationDepsNode *)node;
- if (op_node->owner == other)
- return true;
- else if (op_node->owner->owner == other)
- return true;
- break;
- }
- default: break;
- }
- return false;
-}
-
-static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
- const DepsNode *node)
-{
- DEPSNODE_RELATIONS_ITER_BEGIN(node->inlinks, rel)
- {
- float penwidth = 2.0f;
-
- const DepsNode *tail = rel->to; /* same as node */
- const DepsNode *head = rel->from;
- deg_debug_fprintf(ctx, "// %s -> %s\n",
- head->identifier().c_str(),
- tail->identifier().c_str());
- deg_debug_fprintf(ctx, "\"node_%p\"", head);
- deg_debug_fprintf(ctx, " -> ");
- deg_debug_fprintf(ctx, "\"node_%p\"", tail);
-
- deg_debug_fprintf(ctx, "[");
- /* XXX labels on relations are not very helpful:
- * - they tend to appear too far away to be associated with the edge lines
- * - names are mostly redundant, reflecting simply their from/to nodes
- * - no behavior or typing of relations themselves to justify labels
- */
-#if 0
- deg_debug_fprintf(ctx, "label=\"%s\"", rel->name);
- deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
-#else
- /* Note: without label an id seem necessary to avoid bugs in graphviz/dot */
- deg_debug_fprintf(ctx, "id=\"%s\"", rel->name);
-#endif
- deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_relation_color(ctx, rel);
- deg_debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth);
- /* NOTE: edge from node to own cluster is not possible and gives graphviz
- * warning, avoid this here by just linking directly to the invisible
- * placeholder node
- */
- if (deg_debug_graphviz_is_cluster(tail) && !deg_debug_graphviz_is_owner(head, tail)) {
- deg_debug_fprintf(ctx, ",ltail=\"cluster_%p\"", tail);
- }
- if (deg_debug_graphviz_is_cluster(head) && !deg_debug_graphviz_is_owner(tail, head)) {
- deg_debug_fprintf(ctx, ",lhead=\"cluster_%p\"", head);
- }
- deg_debug_fprintf(ctx, "];" NL);
- deg_debug_fprintf(ctx, NL);
- }
- DEPSNODE_RELATIONS_ITER_END;
-
-#if 0
- if (node->tclass == DEPSNODE_CLASS_COMPONENT) {
- const ComponentDepsNode *comp_node = (const ComponentDepsNode *)node;
- for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin();
- it != comp_node->operations.end();
- ++it)
- {
- OperationDepsNode *op_node = it->second;
- deg_debug_graphviz_node_relations(ctx, op_node);
- }
- }
- else if (node->type == DEPSNODE_TYPE_ID_REF) {
- const IDDepsNode *id_node = (const IDDepsNode *)node;
- for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin();
- it != id_node->components.end();
- ++it)
- {
- const ComponentDepsNode *comp = it->second;
- deg_debug_graphviz_node_relations(ctx, comp);
- }
- }
- else if (node->type == DEPSNODE_TYPE_SUBGRAPH) {
- SubgraphDepsNode *sub_node = (SubgraphDepsNode *)node;
- if (sub_node->graph) {
- deg_debug_graphviz_graph_relations(ctx, sub_node->graph);
- }
- }
-#endif
-}
-
-static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
- const Depsgraph *graph)
-{
- if (graph->root_node) {
- deg_debug_graphviz_node(ctx, graph->root_node);
- }
- for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin();
- it != graph->id_hash.end();
- ++it)
- {
- DepsNode *node = it->second;
- deg_debug_graphviz_node(ctx, node);
- }
- TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
- if (time_source != NULL) {
- deg_debug_graphviz_node(ctx, time_source);
- }
-}
-
-static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
- const Depsgraph *graph)
-{
-#if 0
- if (graph->root_node) {
- deg_debug_graphviz_node_relations(ctx, graph->root_node);
- }
- for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin();
- it != graph->id_hash.end();
- ++it)
- {
- DepsNode *id_node = it->second;
- deg_debug_graphviz_node_relations(ctx, id_node);
- }
-#else
- /* XXX not in use yet */
-// for (Depsgraph::OperationNodes::const_iterator it = graph->all_opnodes.begin();
-// it != graph->all_opnodes.end();
-// ++it)
-// {
-// OperationDepsNode *op_node = *it;
-// deg_debug_graphviz_node_relations(ctx, op_node);
-// }
- for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin();
- it != graph->id_hash.end();
- ++it)
- {
- IDDepsNode *id_node = it->second;
- for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin();
- it != id_node->components.end();
- ++it)
- {
- ComponentDepsNode *comp_node = it->second;
- for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin();
- it != comp_node->operations.end();
- ++it)
- {
- OperationDepsNode *op_node = it->second;
- deg_debug_graphviz_node_relations(ctx, op_node);
- }
- }
- }
-
- TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
- if (time_source != NULL) {
- deg_debug_graphviz_node_relations(ctx, time_source);
- }
-#endif
-}
-
-void DEG_debug_graphviz(const Depsgraph *graph, FILE *f, const char *label, bool show_eval)
-{
-#if 0 /* generate shaded color set */
- static char colors[][3] = {{0xa6, 0xce, 0xe3},{0x1f, 0x78, 0xb4},{0xb2, 0xdf, 0x8a},{0x33, 0xa0, 0x2c},
- {0xfb, 0x9a, 0x99},{0xe3, 0x1a, 0x1c},{0xfd, 0xbf, 0x6f},{0xff, 0x7f, 0x00},
- {0xca, 0xb2, 0xd6},{0x6a, 0x3d, 0x9a},{0xff, 0xff, 0x99},{0xb1, 0x59, 0x28}};
- int i;
- const float factor = 0.666f;
- for (i=0; i < 12; ++i)
- printf("\"#%x%x%x\"\n", (char)(colors[i][0] * factor), (char)(colors[i][1] * factor), (char)(colors[i][2] * factor));
-#endif
-
- if (!graph) {
- return;
- }
-
- DebugContext ctx;
- ctx.file = f;
- ctx.show_tags = show_eval;
- ctx.show_eval_priority = show_eval;
-
- deg_debug_fprintf(ctx, "digraph depgraph {" NL);
- deg_debug_fprintf(ctx, "rankdir=LR;" NL);
- deg_debug_fprintf(ctx, "graph [");
- deg_debug_fprintf(ctx, "compound=true");
- deg_debug_fprintf(ctx, ",labelloc=\"t\"");
- deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_graph_label_size);
- deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
- deg_debug_fprintf(ctx, ",label=\"%s\"", label);
- deg_debug_fprintf(ctx, ",splines=ortho");
- deg_debug_fprintf(ctx, ",overlap=scalexy"); // XXX: only when using neato
- deg_debug_fprintf(ctx, "];" NL);
-
- deg_debug_graphviz_graph_nodes(ctx, graph);
- deg_debug_graphviz_graph_relations(ctx, graph);
-
- deg_debug_graphviz_legend(ctx);
-
- deg_debug_fprintf(ctx, "}" NL);
-}
-
-#undef NL
+#include "intern/eval/deg_eval_debug.h"
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
/* ************************************************ */
-static string get_component_name(eDepsNode_Type type, const string &name = "")
-{
- DepsNodeFactory *factory = DEG_get_node_factory(type);
- if (name.empty()) {
- return string(factory->tname());
- }
- else {
- return string(factory->tname()) + " | " + name;
- }
-}
-
-static void times_clear(DepsgraphStatsTimes &times)
-{
- times.duration_last = 0.0f;
-}
-
-static void times_add(DepsgraphStatsTimes &times, float time)
-{
- times.duration_last += time;
-}
-
-void DepsgraphDebug::eval_begin(const EvaluationContext *UNUSED(eval_ctx))
-{
- /* TODO(sergey): Stats are currently globally disabled. */
- /* verify_stats(); */
- reset_stats();
-}
-
-void DepsgraphDebug::eval_end(const EvaluationContext *UNUSED(eval_ctx))
-{
- WM_main_add_notifier(NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
-}
-
-void DepsgraphDebug::eval_step(const EvaluationContext *UNUSED(eval_ctx),
- const char *message)
-{
-#ifdef DEG_DEBUG_BUILD
- if (deg_debug_eval_cb)
- deg_debug_eval_cb(deg_debug_eval_userdata, message);
-#else
- (void)message; /* Ignored. */
-#endif
-}
-
-void DepsgraphDebug::task_started(Depsgraph *graph,
- const OperationDepsNode *node)
-{
- if (stats) {
- BLI_spin_lock(&graph->lock);
-
- ComponentDepsNode *comp = node->owner;
- ID *id = comp->owner->id;
-
- DepsgraphStatsID *id_stats = get_id_stats(id, true);
- times_clear(id_stats->times);
-
- /* XXX TODO use something like: if (id->flag & ID_DEG_DETAILS) {...} */
- if (0) {
- /* XXX component name usage needs cleanup! currently mixes identifier and description strings! */
- DepsgraphStatsComponent *comp_stats = get_component_stats(id, get_component_name(comp->type, comp->name), true);
- times_clear(comp_stats->times);
- }
-
- BLI_spin_unlock(&graph->lock);
- }
-}
-
-void DepsgraphDebug::task_completed(Depsgraph *graph,
- const OperationDepsNode *node,
- double time)
-{
- if (stats) {
- BLI_spin_lock(&graph->lock);
-
- ComponentDepsNode *comp = node->owner;
- ID *id = comp->owner->id;
-
- DepsgraphStatsID *id_stats = get_id_stats(id, true);
- times_add(id_stats->times, time);
-
- /* XXX TODO use something like: if (id->flag & ID_DEG_DETAILS) {...} */
- if (0) {
- /* XXX component name usage needs cleanup! currently mixes identifier and description strings! */
- DepsgraphStatsComponent *comp_stats = get_component_stats(id, get_component_name(comp->type, comp->name), true);
- times_add(comp_stats->times, time);
- }
-
- BLI_spin_unlock(&graph->lock);
- }
-}
-
-/* ********** */
-/* Statistics */
-
-DepsgraphStats *DepsgraphDebug::stats = NULL;
-
-/* GHash callback */
-static void deg_id_stats_free(void *val)
-{
- DepsgraphStatsID *id_stats = (DepsgraphStatsID *)val;
-
- if (id_stats) {
- BLI_freelistN(&id_stats->components);
- MEM_freeN(id_stats);
- }
-}
-
-void DepsgraphDebug::stats_init()
-{
- if (!stats) {
- stats = (DepsgraphStats *)MEM_callocN(sizeof(DepsgraphStats), "Depsgraph Stats");
- stats->id_stats = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "Depsgraph ID Stats Hash");
- }
-}
-
-void DepsgraphDebug::stats_free()
-{
- if (stats) {
- BLI_ghash_free(stats->id_stats, NULL, deg_id_stats_free);
- MEM_freeN(stats);
- stats = NULL;
- }
-}
-
-void DepsgraphDebug::verify_stats()
-{
- stats_init();
-}
-
-void DepsgraphDebug::reset_stats()
-{
- if (!stats) {
- return;
- }
-
- /* XXX this doesn't work, will immediately clear all info,
- * since most depsgraph updates have none or very few updates to handle.
- *
- * Could consider clearing only zero-user ID blocks here
- */
-// BLI_ghash_clear(stats->id_stats, NULL, deg_id_stats_free);
-}
-
-DepsgraphStatsID *DepsgraphDebug::get_id_stats(ID *id, bool create)
-{
- DepsgraphStatsID *id_stats = (DepsgraphStatsID *)BLI_ghash_lookup(stats->id_stats, id);
-
- if (!id_stats && create) {
- id_stats = (DepsgraphStatsID *)MEM_callocN(sizeof(DepsgraphStatsID), "Depsgraph ID Stats");
- id_stats->id = id;
-
- BLI_ghash_insert(stats->id_stats, id, id_stats);
- }
-
- return id_stats;
-}
-
-DepsgraphStatsComponent *DepsgraphDebug::get_component_stats(
- DepsgraphStatsID *id_stats,
- const string &name,
- bool create)
-{
- DepsgraphStatsComponent *comp_stats;
- for (comp_stats = (DepsgraphStatsComponent *)id_stats->components.first;
- comp_stats != NULL;
- comp_stats = comp_stats->next)
- {
- if (STREQ(comp_stats->name, name.c_str()))
- break;
- }
- if (!comp_stats && create) {
- comp_stats = (DepsgraphStatsComponent *)MEM_callocN(sizeof(DepsgraphStatsComponent), "Depsgraph Component Stats");
- BLI_strncpy(comp_stats->name, name.c_str(), sizeof(comp_stats->name));
- BLI_addtail(&id_stats->components, comp_stats);
- }
- return comp_stats;
-}
-
-/* ------------------------------------------------ */
-
DepsgraphStats *DEG_stats(void)
{
- return DepsgraphDebug::stats;
+ return DEG::DepsgraphDebug::stats;
}
void DEG_stats_verify()
{
- DepsgraphDebug::verify_stats();
+ DEG::DepsgraphDebug::verify_stats();
}
DepsgraphStatsID *DEG_stats_id(ID *id)
{
- if (!DepsgraphDebug::stats) {
+ if (!DEG::DepsgraphDebug::stats) {
return NULL;
}
- return DepsgraphDebug::get_id_stats(id, false);
+ return DEG::DepsgraphDebug::get_id_stats(id, false);
}
bool DEG_debug_compare(const struct Depsgraph *graph1,
@@ -987,7 +70,9 @@ bool DEG_debug_compare(const struct Depsgraph *graph1,
{
BLI_assert(graph1 != NULL);
BLI_assert(graph2 != NULL);
- if (graph1->operations.size() != graph2->operations.size()) {
+ const DEG::Depsgraph *deg_graph1 = reinterpret_cast<const DEG::Depsgraph *>(graph1);
+ const DEG::Depsgraph *deg_graph2 = reinterpret_cast<const DEG::Depsgraph *>(graph2);
+ if (deg_graph1->operations.size() != deg_graph2->operations.size()) {
return false;
}
/* TODO(sergey): Currently we only do real stupid check,
@@ -1017,34 +102,21 @@ bool DEG_debug_scene_relations_validate(Main *bmain,
bool DEG_debug_consistency_check(Depsgraph *graph)
{
- /* Validate links exists in both directions. */
- for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
- it_op != graph->operations.end();
- ++it_op)
- {
- OperationDepsNode *node = *it_op;
- for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
- it_rel != node->outlinks.end();
- ++it_rel)
- {
- DepsRelation *rel = *it_rel;
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ /* Validate links exists in both directions. */
+ foreach (DEG::OperationDepsNode *node, deg_graph->operations) {
+ foreach (DEG::DepsRelation *rel, node->outlinks) {
int counter1 = 0;
- for (OperationDepsNode::Relations::const_iterator tmp_rel = node->outlinks.begin();
- tmp_rel != node->outlinks.end();
- ++tmp_rel)
- {
- if (*tmp_rel == rel) {
+ foreach (DEG::DepsRelation *tmp_rel, node->outlinks) {
+ if (tmp_rel == rel) {
++counter1;
}
}
int counter2 = 0;
- for (OperationDepsNode::Relations::const_iterator tmp_rel = rel->to->inlinks.begin();
- tmp_rel != rel->to->inlinks.end();
- ++tmp_rel)
- {
- if (*tmp_rel == rel) {
+ foreach (DEG::DepsRelation *tmp_rel, rel->to->inlinks) {
+ if (tmp_rel == rel) {
++counter2;
}
}
@@ -1057,33 +129,18 @@ bool DEG_debug_consistency_check(Depsgraph *graph)
}
}
- for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
- it_op != graph->operations.end();
- ++it_op)
- {
- OperationDepsNode *node = *it_op;
- for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin();
- it_rel != node->inlinks.end();
- ++it_rel)
- {
- DepsRelation *rel = *it_rel;
-
+ foreach (DEG::OperationDepsNode *node, deg_graph->operations) {
+ foreach (DEG::DepsRelation *rel, node->inlinks) {
int counter1 = 0;
- for (OperationDepsNode::Relations::const_iterator tmp_rel = node->inlinks.begin();
- tmp_rel != node->inlinks.end();
- ++tmp_rel)
- {
- if (*tmp_rel == rel) {
+ foreach (DEG::DepsRelation *tmp_rel, node->inlinks) {
+ if (tmp_rel == rel) {
++counter1;
}
}
int counter2 = 0;
- for (OperationDepsNode::Relations::const_iterator tmp_rel = rel->from->outlinks.begin();
- tmp_rel != rel->from->outlinks.end();
- ++tmp_rel)
- {
- if (*tmp_rel == rel) {
+ foreach (DEG::DepsRelation *tmp_rel, rel->from->outlinks) {
+ if (tmp_rel == rel) {
++counter2;
}
}
@@ -1096,32 +153,20 @@ bool DEG_debug_consistency_check(Depsgraph *graph)
}
/* Validate node valency calculated in both directions. */
- for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
- it_op != graph->operations.end();
- ++it_op)
- {
- OperationDepsNode *node = *it_op;
+ foreach (DEG::OperationDepsNode *node, deg_graph->operations) {
node->num_links_pending = 0;
node->done = 0;
}
- for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
- it_op != graph->operations.end();
- ++it_op)
- {
- OperationDepsNode *node = *it_op;
+ foreach (DEG::OperationDepsNode *node, deg_graph->operations) {
if (node->done) {
printf("Node %s is twice in the operations!\n",
node->identifier().c_str());
return false;
}
- for (OperationDepsNode::Relations::const_iterator it_rel = node->outlinks.begin();
- it_rel != node->outlinks.end();
- ++it_rel)
- {
- DepsRelation *rel = *it_rel;
- if (rel->to->type == DEPSNODE_TYPE_OPERATION) {
- OperationDepsNode *to = (OperationDepsNode *)rel->to;
+ foreach (DEG::DepsRelation *rel, node->outlinks) {
+ if (rel->to->type == DEG::DEPSNODE_TYPE_OPERATION) {
+ DEG::OperationDepsNode *to = (DEG::OperationDepsNode *)rel->to;
BLI_assert(to->num_links_pending < to->inlinks.size());
++to->num_links_pending;
}
@@ -1129,18 +174,10 @@ bool DEG_debug_consistency_check(Depsgraph *graph)
node->done = 1;
}
- for (Depsgraph::OperationNodes::const_iterator it_op = graph->operations.begin();
- it_op != graph->operations.end();
- ++it_op)
- {
- OperationDepsNode *node = *it_op;
+ foreach (DEG::OperationDepsNode *node, deg_graph->operations) {
int num_links_pending = 0;
- for (OperationDepsNode::Relations::const_iterator it_rel = node->inlinks.begin();
- it_rel != node->inlinks.end();
- ++it_rel)
- {
- DepsRelation *rel = *it_rel;
- if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
+ foreach (DEG::DepsRelation *rel, node->inlinks) {
+ if (rel->from->type == DEG::DEPSNODE_TYPE_OPERATION) {
++num_links_pending;
}
}
@@ -1166,12 +203,14 @@ bool DEG_debug_consistency_check(Depsgraph *graph)
void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer,
size_t *r_operations, size_t *r_relations)
{
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+
/* number of operations */
if (r_operations) {
/* All operations should be in this list, allowing us to count the total
* number of nodes.
*/
- *r_operations = graph->operations.size();
+ *r_operations = deg_graph->operations.size();
}
/* Count number of outer nodes and/or relations between these. */
@@ -1179,29 +218,21 @@ void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer,
size_t tot_outer = 0;
size_t tot_rels = 0;
- for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin();
- it != graph->id_hash.end();
- ++it)
+ GHASH_FOREACH_BEGIN(DEG::IDDepsNode *, id_node, deg_graph->id_hash)
{
- IDDepsNode *id_node = it->second;
tot_outer++;
- for (IDDepsNode::ComponentMap::const_iterator it = id_node->components.begin();
- it != id_node->components.end();
- ++it)
+ GHASH_FOREACH_BEGIN(DEG::ComponentDepsNode *, comp_node, id_node->components)
{
- ComponentDepsNode *comp_node = it->second;
tot_outer++;
- for (ComponentDepsNode::OperationMap::const_iterator it = comp_node->operations.begin();
- it != comp_node->operations.end();
- ++it)
- {
- OperationDepsNode *op_node = it->second;
+ foreach (DEG::OperationDepsNode *op_node, comp_node->operations) {
tot_rels += op_node->inlinks.size();
}
}
+ GHASH_FOREACH_END();
}
+ GHASH_FOREACH_END();
- TimeSourceDepsNode *time_source = graph->find_time_source(NULL);
+ DEG::TimeSourceDepsNode *time_source = deg_graph->find_time_source(NULL);
if (time_source != NULL) {
tot_rels += time_source->inlinks.size();
}
@@ -1210,4 +241,3 @@ void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer,
if (r_outer) *r_outer = tot_outer;
}
}
-
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index 66535f5214b..f8d40d0e6a8 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -32,11 +32,9 @@
#include "MEM_guardedalloc.h"
-#include "PIL_time.h"
-
extern "C" {
#include "BLI_utildefines.h"
-#include "BLI_task.h"
+#include "BLI_ghash.h"
#include "BKE_depsgraph.h"
#include "BKE_scene.h"
@@ -44,13 +42,13 @@ extern "C" {
#include "DEG_depsgraph.h"
} /* extern "C" */
-#include "atomic_ops.h"
+#include "intern/eval/deg_eval.h"
+#include "intern/eval/deg_eval_flush.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_operation.h"
-#include "depsgraph.h"
-#include "depsnode.h"
-#include "depsnode_component.h"
-#include "depsnode_operation.h"
-#include "depsgraph_debug.h"
+#include "intern/depsgraph.h"
#ifdef WITH_LEGACY_DEPSGRAPH
static bool use_legacy_depsgraph = true;
@@ -118,359 +116,16 @@ void DEG_evaluation_context_free(EvaluationContext *eval_ctx)
MEM_freeN(eval_ctx);
}
-/* ********************** */
-/* Evaluation Entrypoints */
-
-/* Forward declarations. */
-static void schedule_children(TaskPool *pool,
- Depsgraph *graph,
- OperationDepsNode *node,
- const int layers,
- const int thread_id);
-
-struct DepsgraphEvalState {
- EvaluationContext *eval_ctx;
- Depsgraph *graph;
- int layers;
-};
-
-static void deg_task_run_func(TaskPool *pool,
- void *taskdata,
- int thread_id)
-{
- DepsgraphEvalState *state = (DepsgraphEvalState *)BLI_task_pool_userdata(pool);
- OperationDepsNode *node = (OperationDepsNode *)taskdata;
-
- BLI_assert(!node->is_noop() && "NOOP nodes should not actually be scheduled");
-
- /* Should only be the case for NOOPs, which never get to this point. */
- BLI_assert(node->evaluate);
-
- while (true) {
- /* Get context. */
- // TODO: who initialises this? "Init" operations aren't able to initialise it!!!
- /* TODO(sergey): We don't use component contexts at this moment. */
- /* ComponentDepsNode *comp = node->owner; */
- BLI_assert(node->owner != NULL);
-
- /* Since we're not leaving the thread for until the graph branches it is
- * possible to have NO-OP on the way. for which evaluate() will be NULL.
- * but that's all fine, we'll just scheduler it's children.
- */
- if (node->evaluate) {
- /* Take note of current time. */
- double start_time = PIL_check_seconds_timer();
- DepsgraphDebug::task_started(state->graph, node);
-
- /* Perform operation. */
- node->evaluate(state->eval_ctx);
-
- /* Note how long this took. */
- double end_time = PIL_check_seconds_timer();
- DepsgraphDebug::task_completed(state->graph,
- node,
- end_time - start_time);
- }
-
- /* If there's only one outgoing link we try to immediately switch to
- * that node evaluation, without leaving the thread.
- *
- * It's only doable if the child don't have extra relations or all they
- * are satisfied.
- *
- * TODO(sergey): Checks here can be de-duplicated with the ones from
- * schedule_node(), however, how to do it nicely?
- */
- if (node->outlinks.size() == 1) {
- DepsRelation *rel = node->outlinks[0];
- OperationDepsNode *child = (OperationDepsNode *)rel->to;
- BLI_assert(child->type == DEPSNODE_TYPE_OPERATION);
- if (!child->scheduled) {
- int id_layers = child->owner->owner->layers;
- if (!((child->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0 &&
- (id_layers & state->layers) != 0))
- {
- /* Node does not need an update, so can;t continue with the
- * chain and need to switch to another one by leaving the
- * thread.
- */
- break;
- }
- if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
- BLI_assert(child->num_links_pending > 0);
- atomic_sub_uint32(&child->num_links_pending, 1);
- }
- if (child->num_links_pending == 0) {
- bool is_scheduled = atomic_fetch_and_or_uint8((uint8_t *)&child->scheduled, (uint8_t)true);
- if (!is_scheduled) {
- /* Node was not scheduled, switch to it! */
- node = child;
- }
- else {
- /* Someone else scheduled the node, leaving us
- * unemployed in this thread, we're leaving.
- */
- break;
- }
- }
- else {
- /* There are other dependencies on the child, can't do
- * anything in the current thread.
- */
- break;
- }
- }
- else {
- /* Happens when having cyclic dependencies.
- *
- * Nothing to do here, single child was already scheduled, we
- * can leave the thread now.
- */
- break;
- }
- }
- else {
- /* TODO(sergey): It's possible to use one of the outgoing relations
- * as a chain which we'll try to keep alive, but it's a bit more
- * involved change.
- */
- schedule_children(pool, state->graph, node, state->layers, thread_id);
- break;
- }
- }
-}
-
-typedef struct CalculatePengindData {
- Depsgraph *graph;
- int layers;
-} CalculatePengindData;
-
-static void calculate_pending_func(void *data_v, int i)
-{
- CalculatePengindData *data = (CalculatePengindData *)data_v;
- Depsgraph *graph = data->graph;
- int layers = data->layers;
- OperationDepsNode *node = graph->operations[i];
- IDDepsNode *id_node = node->owner->owner;
-
- node->num_links_pending = 0;
- node->scheduled = false;
-
- /* count number of inputs that need updates */
- if ((id_node->layers & layers) != 0 &&
- (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
- {
- DEPSNODE_RELATIONS_ITER_BEGIN(node->inlinks, rel)
- {
- if (rel->from->type == DEPSNODE_TYPE_OPERATION &&
- (rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
- {
- OperationDepsNode *from = (OperationDepsNode *)rel->from;
- IDDepsNode *id_from_node = from->owner->owner;
- if ((id_from_node->layers & layers) != 0 &&
- (from->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
- {
- ++node->num_links_pending;
- }
- }
- }
- DEPSNODE_RELATIONS_ITER_END;
- }
-}
-
-static void calculate_pending_parents(Depsgraph *graph, int layers)
-{
- const int num_operations = graph->operations.size();
- const bool do_threads = num_operations > 256;
- CalculatePengindData data;
- data.graph = graph;
- data.layers = layers;
- BLI_task_parallel_range(0, num_operations, &data, calculate_pending_func, do_threads);
-}
-
-#ifdef USE_EVAL_PRIORITY
-static void calculate_eval_priority(OperationDepsNode *node)
-{
- if (node->done) {
- return;
- }
- node->done = 1;
-
- if (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
- /* XXX standard cost of a node, could be estimated somewhat later on */
- const float cost = 1.0f;
- /* NOOP nodes have no cost */
- node->eval_priority = node->is_noop() ? cost : 0.0f;
-
- for (OperationDepsNode::Relations::const_iterator it = node->outlinks.begin();
- it != node->outlinks.end();
- ++it)
- {
- DepsRelation *rel = *it;
- OperationDepsNode *to = (OperationDepsNode *)rel->to;
- BLI_assert(to->type == DEPSNODE_TYPE_OPERATION);
- calculate_eval_priority(to);
- node->eval_priority += to->eval_priority;
- }
- }
- else {
- node->eval_priority = 0.0f;
- }
-}
-#endif
-
-/* Schedule a node if it needs evaluation.
- * dec_parents: Decrement pending parents count, true when child nodes are scheduled
- * after a task has been completed.
- */
-static void schedule_node(TaskPool *pool, Depsgraph *graph, int layers,
- OperationDepsNode *node, bool dec_parents,
- const int thread_id)
-{
- int id_layers = node->owner->owner->layers;
-
- if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0 &&
- (id_layers & layers) != 0)
- {
- if (dec_parents) {
- BLI_assert(node->num_links_pending > 0);
- atomic_sub_uint32(&node->num_links_pending, 1);
- }
-
- if (node->num_links_pending == 0) {
- bool is_scheduled = atomic_fetch_and_or_uint8((uint8_t *)&node->scheduled, (uint8_t)true);
- if (!is_scheduled) {
- if (node->is_noop()) {
- /* skip NOOP node, schedule children right away */
- schedule_children(pool, graph, node, layers, thread_id);
- }
- else {
- /* children are scheduled once this task is completed */
- BLI_task_pool_push_from_thread(pool,
- deg_task_run_func,
- node,
- false,
- TASK_PRIORITY_LOW,
- thread_id);
- }
- }
- }
- }
-}
-
-static void schedule_graph(TaskPool *pool,
- Depsgraph *graph,
- const int layers)
-{
- for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
- it != graph->operations.end();
- ++it)
- {
- OperationDepsNode *node = *it;
- schedule_node(pool, graph, layers, node, false, 0);
- }
-}
-
-static void schedule_children(TaskPool *pool,
- Depsgraph *graph,
- OperationDepsNode *node,
- const int layers,
- const int thread_id)
-{
- DEPSNODE_RELATIONS_ITER_BEGIN(node->outlinks, rel)
- {
- OperationDepsNode *child = (OperationDepsNode *)rel->to;
- BLI_assert(child->type == DEPSNODE_TYPE_OPERATION);
- if (child->scheduled) {
- /* Happens when having cyclic dependencies. */
- continue;
- }
- schedule_node(pool, graph, layers, child, (rel->flag & DEPSREL_FLAG_CYCLIC) == 0, thread_id);
- }
- DEPSNODE_RELATIONS_ITER_END;
-}
-
-/**
- * Evaluate all nodes tagged for updating,
- * \warning This is usually done as part of main loop, but may also be
- * called from frame-change update.
- *
- * \note Time sources should be all valid!
- */
-void DEG_evaluate_on_refresh_ex(EvaluationContext *eval_ctx,
- Depsgraph *graph,
- const int layers)
-{
- /* Generate base evaluation context, upon which all the others are derived. */
- // TODO: this needs both main and scene access...
-
- /* Nothing to update, early out. */
- if (graph->entry_tags.size() == 0) {
- return;
- }
-
- /* Set time for the current graph evaluation context. */
- TimeSourceDepsNode *time_src = graph->find_time_source();
- eval_ctx->ctime = time_src->cfra;
-
- /* XXX could use a separate pool for each eval context */
- DepsgraphEvalState state;
- state.eval_ctx = eval_ctx;
- state.graph = graph;
- state.layers = layers;
-
- TaskScheduler *task_scheduler = BLI_task_scheduler_get();
- TaskPool *task_pool = BLI_task_pool_create(task_scheduler, &state);
-
- if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
- BLI_pool_set_num_threads(task_pool, 1);
- }
-
- calculate_pending_parents(graph, layers);
-
- /* Clear tags. */
- for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
- it != graph->operations.end();
- ++it)
- {
- OperationDepsNode *node = *it;
- node->done = 0;
- }
-
- /* Calculate priority for operation nodes. */
-#ifdef USE_EVAL_PRIORITY
- for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
- it != graph->operations.end();
- ++it)
- {
- OperationDepsNode *node = *it;
- calculate_eval_priority(node);
- }
-#endif
-
- DepsgraphDebug::eval_begin(eval_ctx);
-
- schedule_graph(task_pool, graph, layers);
-
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
-
- DepsgraphDebug::eval_end(eval_ctx);
-
- /* Clear any uncleared tags - just in case. */
- DEG_graph_clear_tags(graph);
-}
-
/* Evaluate all nodes tagged for updating. */
void DEG_evaluate_on_refresh(EvaluationContext *eval_ctx,
Depsgraph *graph,
Scene *scene)
{
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
/* Update time on primary timesource. */
- TimeSourceDepsNode *tsrc = graph->find_time_source();
+ DEG::TimeSourceDepsNode *tsrc = deg_graph->find_time_source();
tsrc->cfra = BKE_scene_frame_get(scene);
-
- DEG_evaluate_on_refresh_ex(eval_ctx, graph, graph->layers);
+ DEG::deg_evaluate_on_refresh(eval_ctx, deg_graph, deg_graph->layers);
}
/* Frame-change happened for root scene that graph belongs to. */
@@ -480,19 +135,18 @@ void DEG_evaluate_on_framechange(EvaluationContext *eval_ctx,
float ctime,
const int layers)
{
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
/* Update time on primary timesource. */
- TimeSourceDepsNode *tsrc = graph->find_time_source();
+ DEG::TimeSourceDepsNode *tsrc = deg_graph->find_time_source();
tsrc->cfra = ctime;
-
- tsrc->tag_update(graph);
-
- DEG_graph_flush_updates(bmain, graph);
-
+ tsrc->tag_update(deg_graph);
+ DEG::deg_graph_flush_updates(bmain, deg_graph);
/* Perform recalculation updates. */
- DEG_evaluate_on_refresh_ex(eval_ctx, graph, layers);
+ DEG::deg_evaluate_on_refresh(eval_ctx, deg_graph, layers);
}
bool DEG_needs_eval(Depsgraph *graph)
{
- return graph->entry_tags.size() != 0;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ return BLI_gset_size(deg_graph->entry_tags) != 0;
}
diff --git a/source/blender/depsgraph/intern/depsgraph_intern.h b/source/blender/depsgraph/intern/depsgraph_intern.h
index 7fdc2454564..e5d3d1f5861 100644
--- a/source/blender/depsgraph/intern/depsgraph_intern.h
+++ b/source/blender/depsgraph/intern/depsgraph_intern.h
@@ -31,65 +31,26 @@
* - Also, defines for "Node Type Info"
*/
-#ifndef __DEPSGRAPH_INTERN_H__
-#define __DEPSGRAPH_INTERN_H__
+#pragma once
#include <cstdlib>
#include "MEM_guardedalloc.h"
-#include "depsgraph.h"
-#include "depsnode.h"
+extern "C" {
+#include "BKE_global.h"
+}
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+#include "intern/depsgraph.h"
struct Main;
struct Group;
struct Scene;
-/* Graph Building ======================================================== */
-
-/**
- * Build depsgraph for the given group, and dump results in given graph container
- * This is usually used for building subgraphs for groups to use...
- */
-void DEG_graph_build_from_group(Depsgraph *graph, struct Main *bmain, struct Group *group);
-
-/* Build subgraph for group */
-DepsNode *DEG_graph_build_group_subgraph(Depsgraph *graph_main, struct Main *bmain, struct Group *group);
-
-/* Graph Copying ========================================================= */
-/* (Part of the Filtering API) */
-
-/**
- * Depsgraph Copying Context (dcc)
- *
- * Keeps track of node relationships/links/etc. during the copy
- * operation so that they can be safely remapped...
- */
-typedef struct DepsgraphCopyContext {
- struct GHash *nodes_hash; /* <DepsNode, DepsNode> mapping from src node to dst node */
- struct GHash *rels_hash; // XXX: same for relationships?
-
- // XXX: filtering criteria...
-} DepsgraphCopyContext;
-
-/* Internal Filtering API ---------------------------------------------- */
-
-/* Create filtering context */
-// XXX: needs params for conditions?
-DepsgraphCopyContext *DEG_filter_init(void);
-
-/* Free filtering context once filtering is done */
-void DEG_filter_cleanup(DepsgraphCopyContext *dcc);
-
-
-/* Data Copy Operations ------------------------------------------------ */
-
-/**
- * Make a (deep) copy of provided node and it's little subgraph
- * \warning Newly created node is not added to the existing graph
- * \param dcc: Context info for helping resolve links
- */
-DepsNode *DEG_copy_node(DepsgraphCopyContext *dcc, const DepsNode *src);
+namespace DEG {
/* Node Types Handling ================================================= */
@@ -101,8 +62,9 @@ struct DepsNodeFactory {
virtual eDepsNode_Class tclass() const = 0;
virtual const char *tname() const = 0;
- virtual DepsNode *create_node(const ID *id, const string &subdata, const string &name) const = 0;
- virtual DepsNode *copy_node(DepsgraphCopyContext *dcc, const DepsNode *copy) const = 0;
+ virtual DepsNode *create_node(const ID *id,
+ const string &subdata,
+ const string &name) const = 0;
};
template <class NodeType>
@@ -130,34 +92,18 @@ struct DepsNodeFactoryImpl : public DepsNodeFactory {
return node;
}
-
- virtual DepsNode *copy_node(DepsgraphCopyContext *dcc, const DepsNode *copy) const
- {
- BLI_assert(copy->type == type());
- DepsNode *node = OBJECT_GUARDED_NEW(NodeType);
-
- /* populate base node settings */
- node->type = type();
- node->tclass = tclass();
- // XXX: need to review the name here, as we can't have exact duplicates...
- node->name = copy->name;
-
- node->copy(dcc, static_cast<const NodeType *>(copy));
-
- return node;
- }
};
/* Typeinfo Management -------------------------------------------------- */
/* Register typeinfo */
-void DEG_register_node_typeinfo(DepsNodeFactory *factory);
+void deg_register_node_typeinfo(DepsNodeFactory *factory);
/* Get typeinfo for specified type */
-DepsNodeFactory *DEG_get_node_factory(const eDepsNode_Type type);
+DepsNodeFactory *deg_get_node_factory(const eDepsNode_Type type);
/* Get typeinfo for provided node */
-DepsNodeFactory *DEG_node_get_factory(const DepsNode *node);
+DepsNodeFactory *deg_node_get_factory(const DepsNode *node);
/* Editors Integration -------------------------------------------------- */
@@ -165,4 +111,11 @@ void deg_editors_id_update(struct Main *bmain, struct ID *id);
void deg_editors_scene_update(struct Main *bmain, struct Scene *scene, bool updated);
-#endif /* __DEPSGRAPH_INTERN_H__ */
+#define DEG_DEBUG_PRINTF(...) \
+ do { \
+ if (G.debug & G_DEBUG_DEPSGRAPH) { \
+ fprintf(stderr, __VA_ARGS__); \
+ } \
+ } while (0)
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index 73193747b93..cac4eaae215 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -33,162 +33,12 @@
#include "MEM_guardedalloc.h"
extern "C" {
-#include "BLI_utildefines.h"
-#include "BLI_ghash.h"
-
#include "BKE_main.h"
#include "DEG_depsgraph_query.h"
} /* extern "C" */
-#include "depsgraph_queue.h"
-#include "depsnode.h"
-#include "depsnode_operation.h"
-#include "depsgraph_intern.h"
-
-/* ************************* */
-/* Low-Level Graph Traversal */
-
-#if 0
-/* Prepare for graph traversal, by tagging nodes, etc. */
-static void DEG_graph_traverse_begin(Depsgraph * /*graph*/)
-{
- /* go over all nodes, initialising the valence counts */
- // XXX: this will end up being O(|V|), which is bad when we're just updating a few nodes...
-}
-
-/* Perform a traversal of graph from given starting node (in execution order) */
-// TODO: additional flags for controlling the process?
-void DEG_graph_traverse_from_node(Depsgraph *graph, OperationDepsNode *start_node,
- DEG_FilterPredicate filter, void *filter_data,
- DEG_NodeOperation op, void *operation_data)
-{
- DepsgraphQueue *q;
-
- /* sanity checks */
- if (ELEM(NULL, graph, start_node, op))
- return;
-
- /* add node as starting node to be evaluated, with value of 0 */
- q = DEG_queue_new();
-
- start_node->num_links_pending = 0;
- DEG_queue_push(q, start_node, 0.0f);
-
- /* while we still have nodes in the queue, grab and work on next one */
- do {
- /* grab item at front of queue */
- // XXX: in practice, we may need to wait until one becomes available...
- OperationDepsNode *node = (OperationDepsNode *)DEG_queue_pop(q);
-
- /* perform operation on node */
- op(graph, node, operation_data);
-
- /* schedule up operations which depend on this */
- DEPSNODE_RELATIONS_ITER_BEGIN(node->outlinks, rel)
- {
- /* ensure that relationship is not tagged for ignoring (i.e. cyclic, etc.) */
- // TODO: cyclic refs should probably all get clustered towards the end, so that we can just stop on the first one
- if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
- OperationDepsNode *child_node = (OperationDepsNode *)rel->to;
-
- /* only visit node if the filtering function agrees */
- if ((filter == NULL) || filter(graph, child_node, filter_data)) {
- /* schedule up node... */
- child_node->num_links_pending--;
- DEG_queue_push(q, child_node, (float)child_node->num_links_pending);
- }
- }
- }
- DEPSNODE_RELATIONS_ITER_END;
- } while (DEG_queue_is_empty(q) == false);
-
- /* cleanup */
- DEG_queue_free(q);
-}
-#endif
-
-/* ************************************************************** */
-/* Filtering API - Basically, making a copy of the existing graph */
-
-/* Create filtering context */
-// TODO: allow passing in a number of criteria?
-DepsgraphCopyContext *DEG_filter_init()
-{
- DepsgraphCopyContext *dcc = (DepsgraphCopyContext *)MEM_callocN(sizeof(DepsgraphCopyContext), "DepsgraphCopyContext");
-
- /* init hashes for easy lookups */
- dcc->nodes_hash = BLI_ghash_ptr_new("Depsgraph Filter NodeHash");
- dcc->rels_hash = BLI_ghash_ptr_new("Depsgraph Filter Relationship Hash"); // XXX?
-
- /* store filtering criteria? */
- // xxx...
-
- return dcc;
-}
-
-/* Cleanup filtering context */
-void DEG_filter_cleanup(DepsgraphCopyContext *dcc)
-{
- /* sanity check */
- if (dcc == NULL)
- return;
-
- /* free hashes - contents are weren't copied, so are ok... */
- BLI_ghash_free(dcc->nodes_hash, NULL, NULL);
- BLI_ghash_free(dcc->rels_hash, NULL, NULL);
-
- /* clear filtering criteria */
- // ...
-
- /* free dcc itself */
- MEM_freeN(dcc);
-}
-
-/* -------------------------------------------------- */
-
-/* Create a copy of provided node */
-// FIXME: the handling of sub-nodes and links will need to be subject to filtering options...
-// XXX: perhaps this really shouldn't be exposed, as it will just be a sub-step of the evaluation process?
-DepsNode *DEG_copy_node(DepsgraphCopyContext *dcc, const DepsNode *src)
-{
- /* sanity check */
- if (src == NULL)
- return NULL;
-
- DepsNodeFactory *factory = DEG_get_node_factory(src->type);
- BLI_assert(factory != NULL);
- DepsNode *dst = factory->copy_node(dcc, src);
-
- /* add this node-pair to the hash... */
- BLI_ghash_insert(dcc->nodes_hash, (DepsNode *)src, dst);
-
-#if 0 /* XXX TODO */
- /* now, fix up any links in standard "node header" (i.e. DepsNode struct, that all
- * all others are derived from) that are now corrupt
- */
- {
- /* relationships to other nodes... */
- // FIXME: how to handle links? We may only have partial set of all nodes still?
- // XXX: the exact details of how to handle this are really part of the querying API...
-
- // XXX: BUT, for copying subgraphs, we'll need to define an API for doing this stuff anyways
- // (i.e. for resolving and patching over links that exist within subtree...)
- dst->inlinks.clear();
- dst->outlinks.clear();
-
- /* clear traversal data */
- dst->num_links_pending = 0;
- dst->lasttime = 0;
- }
-
- /* fix links */
- // XXX...
-#endif
-
- /* return copied node */
- return dst;
-}
+#include "intern/depsgraph_intern.h"
bool DEG_id_type_tagged(Main *bmain, short idtype)
{
@@ -207,7 +57,9 @@ short DEG_get_eval_flags_for_id(Depsgraph *graph, ID *id)
return 0;
}
- IDDepsNode *id_node = graph->find_id_node(id);
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+
+ DEG::IDDepsNode *id_node = deg_graph->find_id_node(id);
if (id_node == NULL) {
/* TODO(sergey): Does it mean we need to check set scene? */
return 0;
diff --git a/source/blender/depsgraph/intern/depsgraph_queue.cc b/source/blender/depsgraph/intern/depsgraph_queue.cc
deleted file mode 100644
index da60d73bc46..00000000000
--- a/source/blender/depsgraph/intern/depsgraph_queue.cc
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2013 Blender Foundation.
- * All rights reserved.
- *
- * Original Author: Joshua Leung
- * Contributor(s): None Yet
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/depsgraph/intern/depsgraph_queue.cc
- * \ingroup depsgraph
- *
- * Implementation of special queue type for use in Depsgraph traversals.
- */
-
-#include <stdlib.h>
-
-#include "MEM_guardedalloc.h"
-
-extern "C" {
-#include "BLI_utildefines.h"
-#include "BLI_heap.h"
-#include "BLI_ghash.h"
-} /* extern "C" */
-
-#include "depsgraph_queue.h"
-
-/* ****************************** */
-/* Depsgraph Queue implementation */
-
-/* Data Management ----------------------------------------- */
-
-DepsgraphQueue *DEG_queue_new(void)
-{
- DepsgraphQueue *q = (DepsgraphQueue *)MEM_callocN(sizeof(DepsgraphQueue), "DEG_queue_new()");
-
- /* init data structures for use here */
- q->pending_heap = BLI_heap_new();
- q->pending_hash = BLI_ghash_ptr_new("DEG Queue Pending Hash");
-
- q->ready_heap = BLI_heap_new();
-
- /* init settings */
- q->idx = 0;
- q->tot = 0;
-
- /* return queue */
- return q;
-}
-
-void DEG_queue_free(DepsgraphQueue *q)
-{
- /* free data structures */
- BLI_assert(BLI_heap_size(q->pending_heap) == 0);
- BLI_assert(BLI_heap_size(q->ready_heap) == 0);
- BLI_assert(BLI_ghash_size(q->pending_hash) == 0);
-
- BLI_heap_free(q->pending_heap, NULL);
- BLI_heap_free(q->ready_heap, NULL);
- BLI_ghash_free(q->pending_hash, NULL, NULL);
-
- /* free queue itself */
- MEM_freeN(q);
-}
-
-/* Statistics --------------------------------------------- */
-
-/* Get the number of nodes which are we should visit, but are not able to yet */
-size_t DEG_queue_num_pending(DepsgraphQueue *q)
-{
- return BLI_heap_size(q->pending_heap);
-}
-
-/* Get the number of nodes which are now ready to be visited */
-size_t DEG_queue_num_ready(DepsgraphQueue *q)
-{
- return BLI_heap_size(q->ready_heap);
-}
-
-/* Get total size of queue */
-size_t DEG_queue_size(DepsgraphQueue *q)
-{
- return DEG_queue_num_pending(q) + DEG_queue_num_ready(q);
-}
-
-/* Check if queue has any items in it (still passing through) */
-bool DEG_queue_is_empty(DepsgraphQueue *q)
-{
- return DEG_queue_size(q) == 0;
-}
-
-/* Queue Operations --------------------------------------- */
-
-/**
- * Add DepsNode to the queue
- * \param dnode: ``(DepsNode *)`` node to add to the queue
- * Each node is only added once to the queue; Subsequent pushes
- * merely update its status (e.g. moving it from "pending" to "ready")
- * \param cost: new "num_links_pending" count for node *after* it has encountered
- * via an outlink from the node currently being visited
- * (i.e. we're one of the dependencies which may now be able to be processed)
- */
-void DEG_queue_push(DepsgraphQueue *q, void *dnode, float cost)
-{
- HeapNode *hnode = NULL;
-
- /* Shortcut: Directly add to ready if node isn't waiting on anything now... */
- if (cost == 0) {
- /* node is now ready to be visited - schedule it up for such */
- if (BLI_ghash_haskey(q->pending_hash, dnode)) {
- /* remove from pending queue - we're moving it to the scheduling queue */
- hnode = (HeapNode *)BLI_ghash_lookup(q->pending_hash, dnode);
- BLI_heap_remove(q->pending_heap, hnode);
-
- BLI_ghash_remove(q->pending_hash, dnode, NULL, NULL);
- }
-
- /* schedule up node using latest count (of ready nodes) */
- BLI_heap_insert(q->ready_heap, (float)q->idx, dnode);
- q->idx++;
- }
- else {
- /* node is still waiting on some other ancestors,
- * so add it to the pending heap in the meantime...
- */
- // XXX: is this even necessary now?
- if (BLI_ghash_haskey(q->pending_hash, dnode)) {
- /* just update cost on pending node */
- hnode = (HeapNode *)BLI_ghash_lookup(q->pending_hash, dnode);
- BLI_heap_remove(q->pending_heap, hnode);
- BLI_heap_insert(q->pending_heap, cost, hnode);
- }
- else {
- /* add new node to pending queue, and increase size of overall queue */
- hnode = BLI_heap_insert(q->pending_heap, cost, dnode);
- q->tot++;
- }
- }
-}
-
-/* Grab a "ready" node from the queue */
-void *DEG_queue_pop(DepsgraphQueue *q)
-{
- /* sanity check: if there are no "ready" nodes,
- * start pulling from "pending" to keep things moving,
- * but throw a warning so that we know that something's up here...
- */
- if (BLI_heap_is_empty(q->ready_heap)) {
- // XXX: this should never happen
- // XXX: if/when it does happen, we may want instead to just wait until something pops up here...
- printf("DepsgraphHeap Warning: No more ready nodes available. Trying from pending (idx = %d, tot = %d, pending = %d, ready = %d)\n",
- (int)q->idx, (int)q->tot, (int)DEG_queue_num_pending(q), (int)DEG_queue_num_ready(q));
-
- return BLI_heap_popmin(q->pending_heap);
- }
- else {
- /* only grab "ready" nodes */
- return BLI_heap_popmin(q->ready_heap);
- }
-}
diff --git a/source/blender/depsgraph/intern/depsgraph_queue.h b/source/blender/depsgraph/intern/depsgraph_queue.h
deleted file mode 100644
index b85d46bd173..00000000000
--- a/source/blender/depsgraph/intern/depsgraph_queue.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2013 Blender Foundation.
- * All rights reserved.
- *
- * Original Author: Joshua Leung
- * Contributor(s): None Yet
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/depsgraph/intern/depsgraph_queue.h
- * \ingroup depsgraph
- *
- * Defines for special queue type for use in Depsgraph traversals.
- */
-
-#ifndef __DEPSGRAPH_QUEUE_H__
-#define __DEPSGRAPH_QUEUE_H__
-
-struct DepsNode;
-
-struct Heap;
-struct GHash;
-
-/* *********************************************** */
-/* Dependency Graph Traversal Queue
- *
- * There are two parts to this:
- * a) "Pending" Nodes - This part contains the set of nodes
- * which are related to those which have been visited
- * previously, but are not yet ready to actually be visited.
- * b) "Scheduled" Nodes - These are the nodes whose ancestors
- * have all been evaluated already, which means that any
- * or all of them can be picked (in practically in order) to
- * be visited immediately.
- *
- * Internally, the queue makes sure that each node in the graph
- * only gets added to the queue once. This is because there can
- * be multiple inlinks to each node given the way that the relations
- * work.
- */
-
-/* Depsgraph Queue Type */
-typedef struct DepsgraphQueue {
- /* Pending */
- struct Heap *pending_heap; /* (valence:int, DepsNode*) */
- struct GHash *pending_hash; /* (DepsNode* : HeapNode*>) */
-
- /* Ready to be visited - fifo */
- struct Heap *ready_heap; /* (idx:int, DepsNode*) */
-
- /* Size/Order counts */
- size_t idx; /* total number of nodes which are/have been ready so far (including those already visited) */
- size_t tot; /* total number of nodes which have passed through queue; mainly for debug */
-} DepsgraphQueue;
-
-/* ************************** */
-/* Depsgraph Queue Operations */
-
-/* Data management */
-DepsgraphQueue *DEG_queue_new(void);
-void DEG_queue_free(DepsgraphQueue *q);
-
-/* Statistics */
-size_t DEG_queue_num_pending(DepsgraphQueue *q);
-size_t DEG_queue_num_ready(DepsgraphQueue *q);
-
-size_t DEG_queue_size(DepsgraphQueue *q);
-bool DEG_queue_is_empty(DepsgraphQueue *q);
-
-/* Operations */
-void DEG_queue_push(DepsgraphQueue *q, void *dnode, float cost = 0.0f);
-void *DEG_queue_pop(DepsgraphQueue *q);
-
-#endif /* DEPSGRAPH_QUEUE_H */
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index f00bce29f64..7c048751869 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -54,11 +54,14 @@ extern "C" {
#include "DEG_depsgraph.h"
} /* extern "C" */
-#include "depsgraph_debug.h"
-#include "depsnode.h"
-#include "depsnode_component.h"
-#include "depsnode_operation.h"
-#include "depsgraph_intern.h"
+#include "intern/eval/deg_eval_flush.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
/* *********************** */
/* Update Tagging/Flushing */
@@ -126,19 +129,21 @@ void lib_id_recalc_tag_flag(Main *bmain, ID *id, int flag)
*/
void DEG_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id)
{
- IDDepsNode *node = graph->find_id_node(id);
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ DEG::IDDepsNode *node = deg_graph->find_id_node(id);
lib_id_recalc_tag(bmain, id);
if (node != NULL) {
- node->tag_update(graph);
+ node->tag_update(deg_graph);
}
}
/* Tag nodes related to a specific piece of data */
void DEG_graph_data_tag_update(Depsgraph *graph, const PointerRNA *ptr)
{
- DepsNode *node = graph->find_node_from_pointer(ptr, NULL);
- if (node) {
- node->tag_update(graph);
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ DEG::DepsNode *node = deg_graph->find_node_from_pointer(ptr, NULL);
+ if (node != NULL) {
+ node->tag_update(deg_graph);
}
else {
printf("Missing node in %s\n", __func__);
@@ -151,9 +156,10 @@ void DEG_graph_property_tag_update(Depsgraph *graph,
const PointerRNA *ptr,
const PropertyRNA *prop)
{
- DepsNode *node = graph->find_node_from_pointer(ptr, prop);
- if (node) {
- node->tag_update(graph);
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ DEG::DepsNode *node = deg_graph->find_node_from_pointer(ptr, prop);
+ if (node != NULL) {
+ node->tag_update(deg_graph);
}
else {
printf("Missing node in %s\n", __func__);
@@ -223,131 +229,6 @@ void DEG_id_type_tag(Main *bmain, short idtype)
bmain->id_tag_update[((unsigned char *)&idtype)[0]] = 1;
}
-/* Update Flushing ---------------------------------- */
-
-/* FIFO queue for tagged nodes that need flushing */
-/* XXX This may get a dedicated implementation later if needed - lukas */
-typedef std::queue<OperationDepsNode *> FlushQueue;
-
-static void flush_init_func(void *data_v, int i)
-{
- /* ID node's done flag is used to avoid multiple editors update
- * for the same ID.
- */
- Depsgraph *graph = (Depsgraph *)data_v;
- OperationDepsNode *node = graph->operations[i];
- IDDepsNode *id_node = node->owner->owner;
- id_node->done = 0;
- node->scheduled = false;
- node->owner->flags &= ~DEPSCOMP_FULLY_SCHEDULED;
-}
-
-/* Flush updates from tagged nodes outwards until all affected nodes are tagged. */
-void DEG_graph_flush_updates(Main *bmain, Depsgraph *graph)
-{
- /* sanity check */
- if (graph == NULL)
- return;
-
- /* Nothing to update, early out. */
- if (graph->entry_tags.size() == 0) {
- return;
- }
-
- /* TODO(sergey): With a bit of flag magic we can get rid of this
- * extra loop.
- */
- const int num_operations = graph->operations.size();
- const bool do_threads = num_operations > 256;
- BLI_task_parallel_range(0, num_operations, graph, flush_init_func, do_threads);
-
- FlushQueue queue;
- /* Starting from the tagged "entry" nodes, flush outwards... */
- /* NOTE: Also need to ensure that for each of these, there is a path back to
- * root, or else they won't be done.
- * NOTE: Count how many nodes we need to handle - entry nodes may be
- * component nodes which don't count for this purpose!
- */
- for (Depsgraph::EntryTags::const_iterator it = graph->entry_tags.begin();
- it != graph->entry_tags.end();
- ++it)
- {
- OperationDepsNode *node = *it;
- IDDepsNode *id_node = node->owner->owner;
- queue.push(node);
- if (id_node->done == 0) {
- deg_editors_id_update(bmain, id_node->id);
- id_node->done = 1;
- }
- node->scheduled = true;
- }
-
- while (!queue.empty()) {
- OperationDepsNode *node = queue.front();
- queue.pop();
-
- IDDepsNode *id_node = node->owner->owner;
- lib_id_recalc_tag(bmain, id_node->id);
- /* TODO(sergey): For until we've got proper data nodes in the graph. */
- lib_id_recalc_data_tag(bmain, id_node->id);
-
- ID *id = id_node->id;
- /* This code is used to preserve those areas which does direct
- * object update,
- *
- * Plus it ensures visibility changes and relations and layers
- * visibility update has proper flags to work with.
- */
- if (GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- ComponentDepsNode *comp_node = node->owner;
- if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
- object->recalc |= OB_RECALC_TIME;
- }
- else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
- object->recalc |= OB_RECALC_OB;
- }
- else {
- object->recalc |= OB_RECALC_DATA;
- }
- }
-
- /* Flush to nodes along links... */
- for (OperationDepsNode::Relations::const_iterator it = node->outlinks.begin();
- it != node->outlinks.end();
- ++it)
- {
- DepsRelation *rel = *it;
- OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
- if (to_node->scheduled == false) {
- to_node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
- queue.push(to_node);
- to_node->scheduled = true;
- if (id_node->done == 0) {
- deg_editors_id_update(bmain, id_node->id);
- id_node->done = 1;
- }
- }
- }
-
- /* TODO(sergey): For until incremental updates are possible
- * witin a component at least we tag the whole component
- * for update.
- */
- ComponentDepsNode *component = node->owner;
- if ((component->flags & DEPSCOMP_FULLY_SCHEDULED) == 0) {
- for (ComponentDepsNode::OperationMap::iterator it = component->operations.begin();
- it != node->owner->operations.end();
- ++it)
- {
- OperationDepsNode *op = it->second;
- op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
- }
- component->flags |= DEPSCOMP_FULLY_SCHEDULED;
- }
- }
-}
-
/* Recursively push updates out to all nodes dependent on this,
* until all affected are tagged and/or scheduled up for eval
*/
@@ -359,34 +240,17 @@ void DEG_ids_flush_tagged(Main *bmain)
{
/* TODO(sergey): Only visible scenes? */
if (scene->depsgraph != NULL) {
- DEG_graph_flush_updates(bmain, scene->depsgraph);
+ DEG::deg_graph_flush_updates(
+ bmain,
+ reinterpret_cast<DEG::Depsgraph *>(scene->depsgraph));
}
}
}
-static void graph_clear_func(void *data_v, int i)
-{
- Depsgraph *graph = (Depsgraph *)data_v;
- OperationDepsNode *node = graph->operations[i];
- /* Clear node's "pending update" settings. */
- node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE);
-}
-
-/* Clear tags from all operation nodes. */
-void DEG_graph_clear_tags(Depsgraph *graph)
-{
- /* Go over all operation nodes, clearing tags. */
- const int num_operations = graph->operations.size();
- const bool do_threads = num_operations > 256;
- BLI_task_parallel_range(0, num_operations, graph, graph_clear_func, do_threads);
- /* Clear any entry tags which haven't been flushed. */
- graph->entry_tags.clear();
-}
-
/* Update dependency graph when visible scenes/layers changes. */
void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
{
- Depsgraph *graph = scene->depsgraph;
+ DEG::Depsgraph *graph = reinterpret_cast<DEG::Depsgraph *>(scene->depsgraph);
wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
int old_layers = graph->layers;
if (wm != NULL) {
@@ -414,11 +278,8 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
* This is mainly needed on file load only, after that updates of invisible objects
* will be stored in the pending list.
*/
- for (Depsgraph::IDNodeMap::const_iterator it = graph->id_hash.begin();
- it != graph->id_hash.end();
- ++it)
+ GHASH_FOREACH_BEGIN(DEG::IDDepsNode *, id_node, graph->id_hash)
{
- IDDepsNode *id_node = it->second;
ID *id = id_node->id;
if ((id->tag & LIB_TAG_ID_RECALC_ALL) != 0 ||
(id_node->layers & scene->lay_updated) == 0)
@@ -436,14 +297,15 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
(object->recalc & OB_RECALC_ALL) != 0)
{
id_node->tag_update(graph);
- ComponentDepsNode *anim_comp =
- id_node->find_component(DEPSNODE_TYPE_ANIMATION);
+ DEG::ComponentDepsNode *anim_comp =
+ id_node->find_component(DEG::DEPSNODE_TYPE_ANIMATION);
if (anim_comp != NULL && object->recalc & OB_RECALC_TIME) {
anim_comp->tag_update(graph);
}
}
}
}
+ GHASH_FOREACH_END();
}
scene->lay_updated |= graph->layers;
}
@@ -484,7 +346,7 @@ void DEG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
}
}
- deg_editors_scene_update(bmain, scene, (updated || time));
+ DEG::deg_editors_scene_update(bmain, scene, (updated || time));
}
void DEG_ids_clear_recalc(Main *bmain)
diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
index 5a3048a4aa3..97208939e57 100644
--- a/source/blender/depsgraph/intern/depsgraph_type_defines.cc
+++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
@@ -30,6 +30,8 @@
* Defines and code for core node types.
*/
+#include <cstdlib> // for BLI_assert()
+
extern "C" {
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -37,10 +39,13 @@ extern "C" {
#include "DEG_depsgraph.h"
} /* extern "C" */
-#include "depsgraph_intern.h"
-#include "depsnode.h"
-#include "depsnode_component.h"
-#include "depsnode_operation.h"
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "intern/depsgraph_intern.h"
+
+namespace DEG {
/* ************ */
/* External API */
@@ -59,44 +64,108 @@ static GHash *_depsnode_typeinfo_registry = NULL;
/* Registration ------------------------------------------- */
/* Register node type */
-void DEG_register_node_typeinfo(DepsNodeFactory *factory)
+void deg_register_node_typeinfo(DepsNodeFactory *factory)
{
BLI_assert(factory != NULL);
BLI_ghash_insert(_depsnode_typeinfo_registry, SET_INT_IN_POINTER(factory->type()), factory);
}
-/* Register all node types */
-void DEG_register_node_types(void)
-{
- /* initialise registry */
- _depsnode_typeinfo_registry = BLI_ghash_int_new("Depsgraph Node Type Registry");
-
- /* register node types */
- DEG_register_base_depsnodes();
- DEG_register_component_depsnodes();
- DEG_register_operation_depsnodes();
-}
-
-/* Free registry on exit */
-void DEG_free_node_types(void)
-{
- BLI_ghash_free(_depsnode_typeinfo_registry, NULL, NULL);
-}
-
/* Getters ------------------------------------------------- */
/* Get typeinfo for specified type */
-DepsNodeFactory *DEG_get_node_factory(const eDepsNode_Type type)
+DepsNodeFactory *deg_get_node_factory(const eDepsNode_Type type)
{
/* look up type - at worst, it doesn't exist in table yet, and we fail */
return (DepsNodeFactory *)BLI_ghash_lookup(_depsnode_typeinfo_registry, SET_INT_IN_POINTER(type));
}
/* Get typeinfo for provided node */
-DepsNodeFactory *DEG_node_get_factory(const DepsNode *node)
+DepsNodeFactory *deg_node_get_factory(const DepsNode *node)
{
- if (!node)
+ if (node != NULL) {
return NULL;
+ }
+ return deg_get_node_factory(node->type);
+}
+
+/* Stringified opcodes ------------------------------------- */
+
+DepsOperationStringifier DEG_OPNAMES;
- return DEG_get_node_factory(node->type);
+static const char *stringify_opcode(eDepsOperation_Code opcode)
+{
+ switch (opcode) {
+#define STRINGIFY_OPCODE(name) case DEG_OPCODE_##name: return #name
+ STRINGIFY_OPCODE(OPERATION);
+ STRINGIFY_OPCODE(PLACEHOLDER);
+ STRINGIFY_OPCODE(NOOP);
+ STRINGIFY_OPCODE(ANIMATION);
+ STRINGIFY_OPCODE(DRIVER);
+ //STRINGIFY_OPCODE(PROXY);
+ STRINGIFY_OPCODE(TRANSFORM_LOCAL);
+ STRINGIFY_OPCODE(TRANSFORM_PARENT);
+ STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS);
+ //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS_INIT);
+ //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINT);
+ //STRINGIFY_OPCODE(TRANSFORM_CONSTRAINTS_DONE);
+ STRINGIFY_OPCODE(RIGIDBODY_REBUILD);
+ STRINGIFY_OPCODE(RIGIDBODY_SIM);
+ STRINGIFY_OPCODE(TRANSFORM_RIGIDBODY);
+ STRINGIFY_OPCODE(TRANSFORM_FINAL);
+ STRINGIFY_OPCODE(OBJECT_UBEREVAL);
+ STRINGIFY_OPCODE(GEOMETRY_UBEREVAL);
+ STRINGIFY_OPCODE(GEOMETRY_MODIFIER);
+ STRINGIFY_OPCODE(GEOMETRY_PATH);
+ STRINGIFY_OPCODE(POSE_INIT);
+ STRINGIFY_OPCODE(POSE_DONE);
+ STRINGIFY_OPCODE(POSE_IK_SOLVER);
+ STRINGIFY_OPCODE(POSE_SPLINE_IK_SOLVER);
+ STRINGIFY_OPCODE(BONE_LOCAL);
+ STRINGIFY_OPCODE(BONE_POSE_PARENT);
+ STRINGIFY_OPCODE(BONE_CONSTRAINTS);
+ //STRINGIFY_OPCODE(BONE_CONSTRAINTS_INIT);
+ //STRINGIFY_OPCODE(BONE_CONSTRAINT);
+ //STRINGIFY_OPCODE(BONE_CONSTRAINTS_DONE);
+ STRINGIFY_OPCODE(BONE_READY);
+ STRINGIFY_OPCODE(BONE_DONE);
+ STRINGIFY_OPCODE(PSYS_EVAL);
+
+ case DEG_NUM_OPCODES: return "SpecialCase";
+#undef STRINGIFY_OPCODE
+ }
+ return "UNKNOWN";
+}
+
+DepsOperationStringifier::DepsOperationStringifier() {
+ for (int i = 0; i < DEG_NUM_OPCODES; ++i) {
+ names_[i] = stringify_opcode((eDepsOperation_Code)i);
+ }
+}
+
+const char *DepsOperationStringifier::operator[](eDepsOperation_Code opcode) {
+ BLI_assert((opcode > 0) && (opcode < DEG_NUM_OPCODES));
+ if (opcode >= 0 && opcode < DEG_NUM_OPCODES) {
+ return names_[opcode];
+ }
+ return "UnknownOpcode";
+}
+
+} // namespace DEG
+
+/* Register all node types */
+void DEG_register_node_types(void)
+{
+ /* initialise registry */
+ DEG::_depsnode_typeinfo_registry = BLI_ghash_int_new("Depsgraph Node Type Registry");
+
+ /* register node types */
+ DEG::deg_register_base_depsnodes();
+ DEG::deg_register_component_depsnodes();
+ DEG::deg_register_operation_depsnodes();
+}
+
+/* Free registry on exit */
+void DEG_free_node_types(void)
+{
+ BLI_ghash_free(DEG::_depsnode_typeinfo_registry, NULL, NULL);
}
diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h
index f5fbf0bcc76..7516ccbfdc2 100644
--- a/source/blender/depsgraph/intern/depsgraph_types.h
+++ b/source/blender/depsgraph/intern/depsgraph_types.h
@@ -34,10 +34,9 @@
* in the graph.
*/
-#ifndef __DEPSGRAPH_TYPES_H__
-#define __DEPSGRAPH_TYPES_H__
+#pragma once
-#include "depsgraph_util_function.h"
+#include "util/deg_util_function.h"
/* TODO(sergey): Ideally we'll just use char* and statically allocated strings
* to avoid any possible overhead caused by string (re)allocation/formatting.
@@ -55,69 +54,232 @@ struct PointerRNA;
struct EvaluationContext;
struct FCurve;
+namespace DEG {
+
/* Evaluation Operation for atomic operation */
// XXX: move this to another header that can be exposed?
typedef function<void(struct EvaluationContext *)> DepsEvalOperationCb;
-/* Metatype of Nodes - The general "level" in the graph structure the node serves */
+/* Metatype of Nodes - The general "level" in the graph structure
+ * the node serves.
+ */
typedef enum eDepsNode_Class {
- DEPSNODE_CLASS_GENERIC = 0, /* Types generally unassociated with user-visible entities, but needed for graph functioning */
-
- DEPSNODE_CLASS_COMPONENT = 1, /* [Outer Node] An "aspect" of evaluating/updating an ID-Block, requiring certain types of evaluation behaviours */
- DEPSNODE_CLASS_OPERATION = 2, /* [Inner Node] A glorified function-pointer/callback for scheduling up evaluation operations for components, subject to relationship requirements */
+ /* Types generally unassociated with user-visible entities,
+ * but needed for graph functioning.
+ */
+ DEPSNODE_CLASS_GENERIC = 0,
+ /* [Outer Node] An "aspect" of evaluating/updating an ID-Block, requiring
+ * certain types of evaluation behavior.
+ */
+ DEPSNODE_CLASS_COMPONENT = 1,
+ /* [Inner Node] A glorified function-pointer/callback for scheduling up
+ * evaluation operations for components, subject to relationship
+ * requirements.
+ */
+ DEPSNODE_CLASS_OPERATION = 2,
} eDepsNode_Class;
/* Types of Nodes */
typedef enum eDepsNode_Type {
- DEPSNODE_TYPE_UNDEFINED = -1, /* fallback type for invalid return value */
+ /* Fallback type for invalid return value */
+ DEPSNODE_TYPE_UNDEFINED = -1,
+ /* Inner Node (Operation) */
+ DEPSNODE_TYPE_OPERATION = 0,
+
+ /* **** Generic Types **** */
+
+ /* "Current Scene" - basically whatever kicks off the evaluation process. */
+ DEPSNODE_TYPE_ROOT = 1,
+ /* Time-Source */
+ DEPSNODE_TYPE_TIMESOURCE = 2,
+ /* ID-Block reference - used as landmarks/collection point for components,
+ * but not usually part of main graph.
+ */
+ DEPSNODE_TYPE_ID_REF = 3,
+ /* Isolated sub-graph - used for keeping instanced data separate from
+ * instances using them.
+ */
+ DEPSNODE_TYPE_SUBGRAPH = 4,
- DEPSNODE_TYPE_OPERATION = 0, /* Inner Node (Operation) */
+ /* **** Outer Types **** */
- /* Generic Types */
- DEPSNODE_TYPE_ROOT = 1, /* "Current Scene" - basically whatever kicks off the evaluation process */
- DEPSNODE_TYPE_TIMESOURCE = 2, /* Time-Source */
+ /* Parameters Component - Default when nothing else fits
+ * (i.e. just SDNA property setting).
+ */
+ DEPSNODE_TYPE_PARAMETERS = 11,
+ /* Generic "Proxy-Inherit" Component
+ * XXX: Also for instancing of subgraphs?
+ */
+ DEPSNODE_TYPE_PROXY = 12,
+ /* Animation Component
+ *
+ * XXX: merge in with parameters?
+ */
+ DEPSNODE_TYPE_ANIMATION = 13,
+ /* Transform Component (Parenting/Constraints) */
+ DEPSNODE_TYPE_TRANSFORM = 14,
+ /* Geometry Component (DerivedMesh/Displist) */
+ DEPSNODE_TYPE_GEOMETRY = 15,
+ /* Sequencer Component (Scene Only) */
+ DEPSNODE_TYPE_SEQUENCER = 16,
+
+ /* **** Evaluation-Related Outer Types (with Subdata) **** */
+
+ /* Pose Component - Owner/Container of Bones Eval */
+ DEPSNODE_TYPE_EVAL_POSE = 21,
+ /* Bone Component - Child/Subcomponent of Pose */
+ DEPSNODE_TYPE_BONE = 22,
+ /* Particle Systems Component */
+ DEPSNODE_TYPE_EVAL_PARTICLES = 23,
+ /* Material Shading Component */
+ DEPSNODE_TYPE_SHADING = 24,
+} eDepsNode_Type;
- DEPSNODE_TYPE_ID_REF = 3, /* ID-Block reference - used as landmarks/collection point for components, but not usually part of main graph */
- DEPSNODE_TYPE_SUBGRAPH = 4, /* Isolated sub-graph - used for keeping instanced data separate from instances using them */
+/* Identifiers for common operations (as an enum). */
+typedef enum eDepsOperation_Code {
+ /* Generic Operations ------------------------------ */
- /* Outer Types */
- DEPSNODE_TYPE_PARAMETERS = 11, /* Parameters Component - Default when nothing else fits (i.e. just SDNA property setting) */
- DEPSNODE_TYPE_PROXY = 12, /* Generic "Proxy-Inherit" Component */ // XXX: Also for instancing of subgraphs?
- DEPSNODE_TYPE_ANIMATION = 13, /* Animation Component */ // XXX: merge in with parameters?
- DEPSNODE_TYPE_TRANSFORM = 14, /* Transform Component (Parenting/Constraints) */
- DEPSNODE_TYPE_GEOMETRY = 15, /* Geometry Component (DerivedMesh/Displist) */
- DEPSNODE_TYPE_SEQUENCER = 16, /* Sequencer Component (Scene Only) */
+ /* Placeholder for operations which don't need special mention */
+ DEG_OPCODE_OPERATION = 0,
- /* Evaluation-Related Outer Types (with Subdata) */
- DEPSNODE_TYPE_EVAL_POSE = 21, /* Pose Component - Owner/Container of Bones Eval */
- DEPSNODE_TYPE_BONE = 22, /* Bone Component - Child/Subcomponent of Pose */
+ // XXX: Placeholder while porting depsgraph code
+ DEG_OPCODE_PLACEHOLDER,
- DEPSNODE_TYPE_EVAL_PARTICLES = 23, /* Particle Systems Component */
- DEPSNODE_TYPE_SHADING = 24, /* Material Shading Component */
-} eDepsNode_Type;
+ DEG_OPCODE_NOOP,
-/* Identifiers for common operations (as an enum) */
-typedef enum eDepsOperation_Code {
-#define DEF_DEG_OPCODE(label) DEG_OPCODE_##label,
-#include "depsnode_opcodes.h"
-#undef DEF_DEG_OPCODE
+ /* Animation, Drivers, etc. ------------------------ */
+
+ /* NLA + Action */
+ DEG_OPCODE_ANIMATION,
+
+ /* Driver */
+ DEG_OPCODE_DRIVER,
+
+ /* Proxy Inherit? */
+ //DEG_OPCODE_PROXY,
+
+ /* Transform --------------------------------------- */
+
+ /* Transform entry point - local transforms only */
+ DEG_OPCODE_TRANSFORM_LOCAL,
+
+ /* Parenting */
+ DEG_OPCODE_TRANSFORM_PARENT,
+
+ /* Constraints */
+ DEG_OPCODE_TRANSFORM_CONSTRAINTS,
+ //DEG_OPCODE_TRANSFORM_CONSTRAINTS_INIT,
+ //DEG_OPCODE_TRANSFORM_CONSTRAINT,
+ //DEG_OPCODE_TRANSFORM_CONSTRAINTS_DONE,
+
+ /* Rigidbody Sim - Perform Sim */
+ DEG_OPCODE_RIGIDBODY_REBUILD,
+ DEG_OPCODE_RIGIDBODY_SIM,
+
+ /* Rigidbody Sim - Copy Results to Object */
+ DEG_OPCODE_TRANSFORM_RIGIDBODY,
+
+ /* Transform exitpoint */
+ DEG_OPCODE_TRANSFORM_FINAL,
+
+ /* XXX: ubereval is for temporary porting purposes only */
+ DEG_OPCODE_OBJECT_UBEREVAL,
+
+ /* Geometry ---------------------------------------- */
+
+ /* XXX: Placeholder - UberEval */
+ DEG_OPCODE_GEOMETRY_UBEREVAL,
+
+ /* Modifier */
+ DEG_OPCODE_GEOMETRY_MODIFIER,
+
+ /* Curve Objects - Path Calculation (used for path-following tools, */
+ DEG_OPCODE_GEOMETRY_PATH,
+
+ /* Pose -------------------------------------------- */
+
+ /* Init IK Trees, etc. */
+ DEG_OPCODE_POSE_INIT,
+
+ /* Free IK Trees + Compute Deform Matrices */
+ DEG_OPCODE_POSE_DONE,
+
+ /* IK/Spline Solvers */
+ DEG_OPCODE_POSE_IK_SOLVER,
+ DEG_OPCODE_POSE_SPLINE_IK_SOLVER,
+
+ /* Bone -------------------------------------------- */
+
+ /* Bone local transforms - Entrypoint */
+ DEG_OPCODE_BONE_LOCAL,
+
+ /* Pose-space conversion (includes parent + restpose, */
+ DEG_OPCODE_BONE_POSE_PARENT,
+
+ /* Constraints */
+ DEG_OPCODE_BONE_CONSTRAINTS,
+ //DEG_OPCODE_BONE_CONSTRAINTS_INIT,
+ //DEG_OPCODE_BONE_CONSTRAINT,
+ //DEG_OPCODE_BONE_CONSTRAINTS_DONE,
+
+ /* Bone transforms are ready
+ *
+ * - "READY" This (internal, noop is used to signal that all pre-IK
+ * operations are done. Its role is to help mediate situations
+ * where cyclic relations may otherwise form (i.e. one bone in
+ * chain targetting another in same chain,
+ *
+ * - "DONE" This noop is used to signal that the bone's final pose
+ * transform can be read by others
+ */
+ // TODO: deform mats could get calculated in the final_transform ops...
+ DEG_OPCODE_BONE_READY,
+ DEG_OPCODE_BONE_DONE,
+
+ /* Particles --------------------------------------- */
+
+ /* XXX: placeholder - Particle System eval */
+ DEG_OPCODE_PSYS_EVAL,
+
+ DEG_NUM_OPCODES,
} eDepsOperation_Code;
-/* String defines for these opcodes, defined in depsnode_operation.cpp */
-extern const char *DEG_OPNAMES[];
+/* Some magic to stringify operation codes. */
+class DepsOperationStringifier {
+public:
+ DepsOperationStringifier();
+ const char *operator[](eDepsOperation_Code opcodex);
+protected:
+ const char *names_[DEG_NUM_OPCODES];
+};
+/* String defines for these opcodes, defined in depsgraph_type_defines.cpp */
+extern DepsOperationStringifier DEG_OPNAMES;
/* Type of operation */
typedef enum eDepsOperation_Type {
- /* Primary operation types */
- DEPSOP_TYPE_INIT = 0, /* initialise evaluation data */
- DEPSOP_TYPE_EXEC = 1, /* standard evaluation step */
- DEPSOP_TYPE_POST = 2, /* cleanup evaluation data + flush results */
-
- /* Additional operation types */
- DEPSOP_TYPE_OUT = 3, /* indicator for outputting a temporary result that other components can use */ // XXX?
- DEPSOP_TYPE_SIM = 4, /* indicator for things like IK Solvers and Rigidbody Sim steps which modify final results of separate entities at once */
- DEPSOP_TYPE_REBUILD = 5, /* rebuild internal evaluation data - used for Rigidbody Reset and Armature Rebuild-On-Load */
+ /* **** Primary operation types **** */
+
+ /* Initialise evaluation data */
+ DEPSOP_TYPE_INIT = 0,
+ /* Standard evaluation step */
+ DEPSOP_TYPE_EXEC = 1,
+ /* Cleanup evaluation data + flush results */
+ DEPSOP_TYPE_POST = 2,
+
+ /* **** Additional operation types **** */
+ /* Indicator for outputting a temporary result that other components
+ * can use. // XXX?
+ */
+ DEPSOP_TYPE_OUT = 3,
+ /* Indicator for things like IK Solvers and Rigidbody Sim steps which
+ * modify final results of separate entities at once.
+ */
+ DEPSOP_TYPE_SIM = 4,
+ /* Rebuild internal evaluation data - used for Rigidbody Reset and
+ * Armature Rebuild-On-Load.
+ */
+ DEPSOP_TYPE_REBUILD = 5,
} eDepsOperation_Type;
/* Types of relationships between nodes
@@ -170,4 +332,4 @@ typedef enum eDepsRelation_Type {
DEPSREL_TYPE_UPDATE_UI,
} eDepsRelation_Type;
-#endif /* __DEPSGRAPH_TYPES_H__ */
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsnode_opcodes.h b/source/blender/depsgraph/intern/depsnode_opcodes.h
deleted file mode 100644
index b81822c0ac5..00000000000
--- a/source/blender/depsgraph/intern/depsnode_opcodes.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- *
- * Original Author: Joshua Leung
- * Contributor(s): None Yet
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/depsgraph/intern/depsnode_opcodes.h
- * \ingroup depsgraph
- *
- * \par OpCodes for OperationDepsNodes
- *
- * This file defines all the "operation codes" (opcodes) used to identify
- * common operation node types. The intention of these defines is to have
- * a fast and reliable way of identifying the relevant nodes within a component
- * without having to use fragile dynamic strings.
- *
- * This file is meant to be used like UI_icons.h. That is, before including
- * the file, the host file must define the DEG_OPCODE(_label) macro, which
- * is responsible for converting the define into whatever form is suitable.
- * Therefore, it intentionally doesn't have header guards.
- */
-
-
-/* Example macro define: */
-/* #define DEF_DEG_OPCODE(label) DEG_OPCODE_##label, */
-
-/* Generic Operations ------------------------------ */
-
-/* Placeholder for operations which don't need special mention */
-DEF_DEG_OPCODE(OPERATION)
-
-// XXX: Placeholder while porting depsgraph code
-DEF_DEG_OPCODE(PLACEHOLDER)
-
-DEF_DEG_OPCODE(NOOP)
-
-/* Animation, Drivers, etc. ------------------------ */
-
-/* NLA + Action */
-DEF_DEG_OPCODE(ANIMATION)
-
-/* Driver */
-DEF_DEG_OPCODE(DRIVER)
-
-/* Proxy Inherit? */
-//DEF_DEG_OPCODE(PROXY)
-
-/* Transform --------------------------------------- */
-
-/* Transform entry point - local transforms only */
-DEF_DEG_OPCODE(TRANSFORM_LOCAL)
-
-/* Parenting */
-DEF_DEG_OPCODE(TRANSFORM_PARENT)
-
-/* Constraints */
-DEF_DEG_OPCODE(TRANSFORM_CONSTRAINTS)
-//DEF_DEG_OPCODE(TRANSFORM_CONSTRAINTS_INIT)
-//DEF_DEG_OPCODE(TRANSFORM_CONSTRAINT)
-//DEF_DEG_OPCODE(TRANSFORM_CONSTRAINTS_DONE)
-
-/* Rigidbody Sim - Perform Sim */
-DEF_DEG_OPCODE(RIGIDBODY_REBUILD)
-DEF_DEG_OPCODE(RIGIDBODY_SIM)
-
-/* Rigidbody Sim - Copy Results to Object */
-DEF_DEG_OPCODE(TRANSFORM_RIGIDBODY)
-
-/* Transform exitpoint */
-DEF_DEG_OPCODE(TRANSFORM_FINAL)
-
-/* XXX: ubereval is for temporary porting purposes only */
-DEF_DEG_OPCODE(OBJECT_UBEREVAL)
-
-/* Geometry ---------------------------------------- */
-
-/* XXX: Placeholder - UberEval */
-DEF_DEG_OPCODE(GEOMETRY_UBEREVAL)
-
-/* Modifier */
-DEF_DEG_OPCODE(GEOMETRY_MODIFIER)
-
-/* Curve Objects - Path Calculation (used for path-following tools) */
-DEF_DEG_OPCODE(GEOMETRY_PATH)
-
-/* Pose -------------------------------------------- */
-
-/* Init IK Trees, etc. */
-DEF_DEG_OPCODE(POSE_INIT)
-
-/* Free IK Trees + Compute Deform Matrices */
-DEF_DEG_OPCODE(POSE_DONE)
-
-/* IK/Spline Solvers */
-DEF_DEG_OPCODE(POSE_IK_SOLVER)
-DEF_DEG_OPCODE(POSE_SPLINE_IK_SOLVER)
-
-/* Bone -------------------------------------------- */
-
-/* Bone local transforms - Entrypoint */
-DEF_DEG_OPCODE(BONE_LOCAL)
-
-/* Pose-space conversion (includes parent + restpose) */
-DEF_DEG_OPCODE(BONE_POSE_PARENT)
-
-/* Constraints */
-DEF_DEG_OPCODE(BONE_CONSTRAINTS)
-//DEF_DEG_OPCODE(BONE_CONSTRAINTS_INIT)
-//DEF_DEG_OPCODE(BONE_CONSTRAINT)
-//DEF_DEG_OPCODE(BONE_CONSTRAINTS_DONE)
-
-/* Bone transforms are ready
- * - "READY" This (internal) noop is used to signal that all pre-IK operations are done.
- * Its role is to help mediate situations where cyclic relations may otherwise form
- * (i.e. one bone in chain targetting another in same chain)
- * - "DONE" This noop is used to signal that the bone's final pose transform can be read by others
- */
-// TODO: deform mats could get calculated in the final_transform ops...
-DEF_DEG_OPCODE(BONE_READY)
-DEF_DEG_OPCODE(BONE_DONE)
-
-/* Particles --------------------------------------- */
-
-/* XXX: placeholder - Particle System eval */
-DEF_DEG_OPCODE(PSYS_EVAL)
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
new file mode 100644
index 00000000000..198cd349002
--- /dev/null
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -0,0 +1,409 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_eval.cc
+ * \ingroup depsgraph
+ *
+ * Evaluation engine entrypoints for Depsgraph Engine.
+ */
+
+#include "intern/eval/deg_eval.h"
+
+#include "PIL_time.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_task.h"
+#include "BLI_ghash.h"
+
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+
+#include "DEG_depsgraph.h"
+} /* extern "C" */
+
+#include "atomic_ops.h"
+
+#include "intern/eval/deg_eval_debug.h"
+#include "intern/eval/deg_eval_flush.h"
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+#include "intern/depsgraph.h"
+#include "util/deg_util_foreach.h"
+
+/* Unfinished and unused, and takes quite some pre-processing time. */
+#undef USE_EVAL_PRIORITY
+
+/* Use integrated debugger to keep track how much each of the nodes was
+ * evaluating.
+ */
+#undef USE_DEBUGGER
+
+namespace DEG {
+
+/* ********************** */
+/* Evaluation Entrypoints */
+
+/* Forward declarations. */
+static void schedule_children(TaskPool *pool,
+ Depsgraph *graph,
+ OperationDepsNode *node,
+ const int layers,
+ const int thread_id);
+
+struct DepsgraphEvalState {
+ EvaluationContext *eval_ctx;
+ Depsgraph *graph;
+ int layers;
+};
+
+static void deg_task_run_func(TaskPool *pool,
+ void *taskdata,
+ int thread_id)
+{
+ DepsgraphEvalState *state =
+ reinterpret_cast<DepsgraphEvalState *>(BLI_task_pool_userdata(pool));
+ OperationDepsNode *node = reinterpret_cast<OperationDepsNode *>(taskdata);
+
+ BLI_assert(!node->is_noop() && "NOOP nodes should not actually be scheduled");
+
+ /* Should only be the case for NOOPs, which never get to this point. */
+ BLI_assert(node->evaluate);
+
+ while (true) {
+ /* Get context. */
+ /* TODO: Who initialises this? "Init" operations aren't able to
+ * initialise it!!!
+ */
+ /* TODO(sergey): We don't use component contexts at this moment. */
+ /* ComponentDepsNode *comp = node->owner; */
+ BLI_assert(node->owner != NULL);
+
+ /* Since we're not leaving the thread for until the graph branches it is
+ * possible to have NO-OP on the way. for which evaluate() will be NULL.
+ * but that's all fine, we'll just scheduler it's children.
+ */
+ if (node->evaluate) {
+ /* Take note of current time. */
+#ifdef USE_DEBUGGER
+ double start_time = PIL_check_seconds_timer();
+ DepsgraphDebug::task_started(state->graph, node);
+#endif
+
+ /* Perform operation. */
+ node->evaluate(state->eval_ctx);
+
+ /* Note how long this took. */
+#ifdef USE_DEBUGGER
+ double end_time = PIL_check_seconds_timer();
+ DepsgraphDebug::task_completed(state->graph,
+ node,
+ end_time - start_time);
+#endif
+ }
+
+ /* If there's only one outgoing link we try to immediately switch to
+ * that node evaluation, without leaving the thread.
+ *
+ * It's only doable if the child don't have extra relations or all they
+ * are satisfied.
+ *
+ * TODO(sergey): Checks here can be de-duplicated with the ones from
+ * schedule_node(), however, how to do it nicely?
+ */
+ if (node->outlinks.size() == 1) {
+ DepsRelation *rel = node->outlinks[0];
+ OperationDepsNode *child = (OperationDepsNode *)rel->to;
+ BLI_assert(child->type == DEPSNODE_TYPE_OPERATION);
+ if (!child->scheduled) {
+ int id_layers = child->owner->owner->layers;
+ if (!((child->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0 &&
+ (id_layers & state->layers) != 0))
+ {
+ /* Node does not need an update, so can;t continue with the
+ * chain and need to switch to another one by leaving the
+ * thread.
+ */
+ break;
+ }
+ if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
+ BLI_assert(child->num_links_pending > 0);
+ atomic_sub_uint32(&child->num_links_pending, 1);
+ }
+ if (child->num_links_pending == 0) {
+ bool is_scheduled = atomic_fetch_and_or_uint8(
+ (uint8_t *)&child->scheduled, (uint8_t)true);
+ if (!is_scheduled) {
+ /* Node was not scheduled, switch to it! */
+ node = child;
+ }
+ else {
+ /* Someone else scheduled the node, leaving us
+ * unemployed in this thread, we're leaving.
+ */
+ break;
+ }
+ }
+ else {
+ /* There are other dependencies on the child, can't do
+ * anything in the current thread.
+ */
+ break;
+ }
+ }
+ else {
+ /* Happens when having cyclic dependencies.
+ *
+ * Nothing to do here, single child was already scheduled, we
+ * can leave the thread now.
+ */
+ break;
+ }
+ }
+ else {
+ /* TODO(sergey): It's possible to use one of the outgoing relations
+ * as a chain which we'll try to keep alive, but it's a bit more
+ * involved change.
+ */
+ schedule_children(pool, state->graph, node, state->layers, thread_id);
+ break;
+ }
+ }
+}
+
+typedef struct CalculatePengindData {
+ Depsgraph *graph;
+ int layers;
+} CalculatePengindData;
+
+static void calculate_pending_func(void *data_v, int i)
+{
+ CalculatePengindData *data = (CalculatePengindData *)data_v;
+ Depsgraph *graph = data->graph;
+ int layers = data->layers;
+ OperationDepsNode *node = graph->operations[i];
+ IDDepsNode *id_node = node->owner->owner;
+
+ node->num_links_pending = 0;
+ node->scheduled = false;
+
+ /* count number of inputs that need updates */
+ if ((id_node->layers & layers) != 0 &&
+ (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
+ {
+ foreach (DepsRelation *rel, node->inlinks) {
+ if (rel->from->type == DEPSNODE_TYPE_OPERATION &&
+ (rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
+ {
+ OperationDepsNode *from = (OperationDepsNode *)rel->from;
+ IDDepsNode *id_from_node = from->owner->owner;
+ if ((id_from_node->layers & layers) != 0 &&
+ (from->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0)
+ {
+ ++node->num_links_pending;
+ }
+ }
+ }
+ }
+}
+
+static void calculate_pending_parents(Depsgraph *graph, int layers)
+{
+ const int num_operations = graph->operations.size();
+ const bool do_threads = num_operations > 256;
+ CalculatePengindData data;
+ data.graph = graph;
+ data.layers = layers;
+ BLI_task_parallel_range(0,
+ num_operations,
+ &data,
+ calculate_pending_func,
+ do_threads);
+}
+
+#ifdef USE_EVAL_PRIORITY
+static void calculate_eval_priority(OperationDepsNode *node)
+{
+ if (node->done) {
+ return;
+ }
+ node->done = 1;
+
+ if (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ /* XXX standard cost of a node, could be estimated somewhat later on */
+ const float cost = 1.0f;
+ /* NOOP nodes have no cost */
+ node->eval_priority = node->is_noop() ? cost : 0.0f;
+
+ foreach (DepsRelation *rel, node->outlinks) {
+ OperationDepsNode *to = (OperationDepsNode *)rel->to;
+ BLI_assert(to->type == DEPSNODE_TYPE_OPERATION);
+ calculate_eval_priority(to);
+ node->eval_priority += to->eval_priority;
+ }
+ }
+ else {
+ node->eval_priority = 0.0f;
+ }
+}
+#endif
+
+/* Schedule a node if it needs evaluation.
+ * dec_parents: Decrement pending parents count, true when child nodes are
+ * scheduled after a task has been completed.
+ */
+static void schedule_node(TaskPool *pool, Depsgraph *graph, int layers,
+ OperationDepsNode *node, bool dec_parents,
+ const int thread_id)
+{
+ int id_layers = node->owner->owner->layers;
+
+ if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0 &&
+ (id_layers & layers) != 0)
+ {
+ if (dec_parents) {
+ BLI_assert(node->num_links_pending > 0);
+ atomic_sub_uint32(&node->num_links_pending, 1);
+ }
+
+ if (node->num_links_pending == 0) {
+ bool is_scheduled = atomic_fetch_and_or_uint8(
+ (uint8_t *)&node->scheduled, (uint8_t)true);
+ if (!is_scheduled) {
+ if (node->is_noop()) {
+ /* skip NOOP node, schedule children right away */
+ schedule_children(pool, graph, node, layers, thread_id);
+ }
+ else {
+ /* children are scheduled once this task is completed */
+ BLI_task_pool_push_from_thread(pool,
+ deg_task_run_func,
+ node,
+ false,
+ TASK_PRIORITY_LOW,
+ thread_id);
+ }
+ }
+ }
+ }
+}
+
+static void schedule_graph(TaskPool *pool,
+ Depsgraph *graph,
+ const int layers)
+{
+ foreach (OperationDepsNode *node, graph->operations) {
+ schedule_node(pool, graph, layers, node, false, 0);
+ }
+}
+
+static void schedule_children(TaskPool *pool,
+ Depsgraph *graph,
+ OperationDepsNode *node,
+ const int layers,
+ const int thread_id)
+{
+ foreach (DepsRelation *rel, node->outlinks) {
+ OperationDepsNode *child = (OperationDepsNode *)rel->to;
+ BLI_assert(child->type == DEPSNODE_TYPE_OPERATION);
+ if (child->scheduled) {
+ /* Happens when having cyclic dependencies. */
+ continue;
+ }
+ schedule_node(pool,
+ graph,
+ layers,
+ child,
+ (rel->flag & DEPSREL_FLAG_CYCLIC) == 0,
+ thread_id);
+ }
+}
+
+/**
+ * Evaluate all nodes tagged for updating,
+ * \warning This is usually done as part of main loop, but may also be
+ * called from frame-change update.
+ *
+ * \note Time sources should be all valid!
+ */
+void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
+ Depsgraph *graph,
+ const int layers)
+{
+ /* Generate base evaluation context, upon which all the others are derived. */
+ // TODO: this needs both main and scene access...
+
+ /* Nothing to update, early out. */
+ if (BLI_gset_size(graph->entry_tags) == 0) {
+ return;
+ }
+
+ /* Set time for the current graph evaluation context. */
+ TimeSourceDepsNode *time_src = graph->find_time_source();
+ eval_ctx->ctime = time_src->cfra;
+
+ /* XXX could use a separate pool for each eval context */
+ DepsgraphEvalState state;
+ state.eval_ctx = eval_ctx;
+ state.graph = graph;
+ state.layers = layers;
+
+ TaskScheduler *task_scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool = BLI_task_pool_create(task_scheduler, &state);
+
+ if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
+ BLI_pool_set_num_threads(task_pool, 1);
+ }
+
+ calculate_pending_parents(graph, layers);
+
+ /* Clear tags. */
+ foreach (OperationDepsNode *node, graph->operations) {
+ node->done = 0;
+ }
+
+ /* Calculate priority for operation nodes. */
+#ifdef USE_EVAL_PRIORITY
+ foreach (OperationDepsNode *node, graph->operations) {
+ calculate_eval_priority(node);
+ }
+#endif
+
+ DepsgraphDebug::eval_begin(eval_ctx);
+
+ schedule_graph(task_pool, graph, layers);
+
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+
+ DepsgraphDebug::eval_end(eval_ctx);
+
+ /* Clear any uncleared tags - just in case. */
+ deg_graph_clear_tags(graph);
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.h b/source/blender/depsgraph/intern/eval/deg_eval.h
new file mode 100644
index 00000000000..0d42f63433f
--- /dev/null
+++ b/source/blender/depsgraph/intern/eval/deg_eval.h
@@ -0,0 +1,52 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/eval/deg_eval.cc
+ * \ingroup depsgraph
+ *
+ * Evaluation engine entrypoints for Depsgraph Engine.
+ */
+
+#pragma once
+
+struct EvaluationContext;
+
+namespace DEG {
+
+struct Depsgraph;
+
+/**
+ * Evaluate all nodes tagged for updating,
+ * \warning This is usually done as part of main loop, but may also be
+ * called from frame-change update.
+ *
+ * \note Time sources should be all valid!
+ */
+void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
+ Depsgraph *graph,
+ const int layers);
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_debug.cc b/source/blender/depsgraph/intern/eval/deg_eval_debug.cc
new file mode 100644
index 00000000000..67d64aae8bf
--- /dev/null
+++ b/source/blender/depsgraph/intern/eval/deg_eval_debug.cc
@@ -0,0 +1,249 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Lukas Toenne
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/eval/deg_eval_debug.cc
+ * \ingroup depsgraph
+ *
+ * Implementation of tools for debugging the depsgraph
+ */
+
+#include <cstring>
+
+#include "intern/eval/deg_eval_debug.h"
+
+extern "C" {
+#include "BLI_listbase.h"
+#include "BLI_ghash.h"
+
+#include "DEG_depsgraph_debug.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+} /* extern "C" */
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+#include "intern/depsgraph_intern.h"
+
+namespace DEG {
+
+DepsgraphStats *DepsgraphDebug::stats = NULL;
+
+static string get_component_name(eDepsNode_Type type, const string &name = "")
+{
+ DepsNodeFactory *factory = deg_get_node_factory(type);
+ if (name.empty()) {
+ return string(factory->tname());
+ }
+ else {
+ return string(factory->tname()) + " | " + name;
+ }
+}
+
+static void times_clear(DepsgraphStatsTimes &times)
+{
+ times.duration_last = 0.0f;
+}
+
+static void times_add(DepsgraphStatsTimes &times, float time)
+{
+ times.duration_last += time;
+}
+
+void DepsgraphDebug::eval_begin(const EvaluationContext *UNUSED(eval_ctx))
+{
+ /* TODO(sergey): Stats are currently globally disabled. */
+ /* verify_stats(); */
+ reset_stats();
+}
+
+void DepsgraphDebug::eval_end(const EvaluationContext *UNUSED(eval_ctx))
+{
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
+}
+
+void DepsgraphDebug::eval_step(const EvaluationContext *UNUSED(eval_ctx),
+ const char *message)
+{
+#ifdef DEG_DEBUG_BUILD
+ if (deg_debug_eval_cb)
+ deg_debug_eval_cb(deg_debug_eval_userdata, message);
+#else
+ (void)message; /* Ignored. */
+#endif
+}
+
+void DepsgraphDebug::task_started(Depsgraph *graph,
+ const OperationDepsNode *node)
+{
+ if (stats) {
+ BLI_spin_lock(&graph->lock);
+
+ ComponentDepsNode *comp = node->owner;
+ ID *id = comp->owner->id;
+
+ DepsgraphStatsID *id_stats = get_id_stats(id, true);
+ times_clear(id_stats->times);
+
+ /* XXX TODO use something like: if (id->flag & ID_DEG_DETAILS) {...} */
+ if (0) {
+ /* XXX component name usage needs cleanup! currently mixes identifier
+ * and description strings!
+ */
+ DepsgraphStatsComponent *comp_stats =
+ get_component_stats(id, get_component_name(comp->type,
+ comp->name),
+ true);
+ times_clear(comp_stats->times);
+ }
+
+ BLI_spin_unlock(&graph->lock);
+ }
+}
+
+void DepsgraphDebug::task_completed(Depsgraph *graph,
+ const OperationDepsNode *node,
+ double time)
+{
+ if (stats) {
+ BLI_spin_lock(&graph->lock);
+
+ ComponentDepsNode *comp = node->owner;
+ ID *id = comp->owner->id;
+
+ DepsgraphStatsID *id_stats = get_id_stats(id, true);
+ times_add(id_stats->times, time);
+
+ /* XXX TODO use something like: if (id->flag & ID_DEG_DETAILS) {...} */
+ if (0) {
+ /* XXX component name usage needs cleanup! currently mixes identifier
+ * and description strings!
+ */
+ DepsgraphStatsComponent *comp_stats =
+ get_component_stats(id,
+ get_component_name(comp->type,
+ comp->name),
+ true);
+ times_add(comp_stats->times, time);
+ }
+
+ BLI_spin_unlock(&graph->lock);
+ }
+}
+
+/* ********** */
+/* Statistics */
+
+
+/* GHash callback */
+static void deg_id_stats_free(void *val)
+{
+ DepsgraphStatsID *id_stats = (DepsgraphStatsID *)val;
+
+ if (id_stats) {
+ BLI_freelistN(&id_stats->components);
+ MEM_freeN(id_stats);
+ }
+}
+
+void DepsgraphDebug::stats_init()
+{
+ if (!stats) {
+ stats = (DepsgraphStats *)MEM_callocN(sizeof(DepsgraphStats),
+ "Depsgraph Stats");
+ stats->id_stats = BLI_ghash_new(BLI_ghashutil_ptrhash,
+ BLI_ghashutil_ptrcmp,
+ "Depsgraph ID Stats Hash");
+ }
+}
+
+void DepsgraphDebug::stats_free()
+{
+ if (stats) {
+ BLI_ghash_free(stats->id_stats, NULL, deg_id_stats_free);
+ MEM_freeN(stats);
+ stats = NULL;
+ }
+}
+
+void DepsgraphDebug::verify_stats()
+{
+ stats_init();
+}
+
+void DepsgraphDebug::reset_stats()
+{
+ if (!stats) {
+ return;
+ }
+
+ /* XXX this doesn't work, will immediately clear all info,
+ * since most depsgraph updates have none or very few updates to handle.
+ *
+ * Could consider clearing only zero-user ID blocks here
+ */
+// BLI_ghash_clear(stats->id_stats, NULL, deg_id_stats_free);
+}
+
+DepsgraphStatsID *DepsgraphDebug::get_id_stats(ID *id, bool create)
+{
+ DepsgraphStatsID *id_stats = (DepsgraphStatsID *)BLI_ghash_lookup(stats->id_stats, id);
+
+ if (!id_stats && create) {
+ id_stats = (DepsgraphStatsID *)MEM_callocN(sizeof(DepsgraphStatsID),
+ "Depsgraph ID Stats");
+ id_stats->id = id;
+
+ BLI_ghash_insert(stats->id_stats, id, id_stats);
+ }
+
+ return id_stats;
+}
+
+DepsgraphStatsComponent *DepsgraphDebug::get_component_stats(
+ DepsgraphStatsID *id_stats,
+ const string &name,
+ bool create)
+{
+ DepsgraphStatsComponent *comp_stats;
+ for (comp_stats = (DepsgraphStatsComponent *)id_stats->components.first;
+ comp_stats != NULL;
+ comp_stats = comp_stats->next)
+ {
+ if (STREQ(comp_stats->name, name.c_str()))
+ break;
+ }
+ if (!comp_stats && create) {
+ comp_stats = (DepsgraphStatsComponent *)MEM_callocN(sizeof(DepsgraphStatsComponent),
+ "Depsgraph Component Stats");
+ BLI_strncpy(comp_stats->name, name.c_str(), sizeof(comp_stats->name));
+ BLI_addtail(&id_stats->components, comp_stats);
+ }
+ return comp_stats;
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.h b/source/blender/depsgraph/intern/eval/deg_eval_debug.h
index 64b97855f57..9109019eb2d 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.h
+++ b/source/blender/depsgraph/intern/eval/deg_eval_debug.h
@@ -24,27 +24,26 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/intern/depsgraph_debug.h
+/** \file blender/depsgraph/intern/eval/deg_eval_debug.h
* \ingroup depsgraph
*/
-#ifndef __DEPSGRAPH_DEBUG_H__
-#define __DEPSGRAPH_DEBUG_H__
+#pragma once
-#include "depsgraph_types.h"
+#include "intern/depsgraph_types.h"
-extern "C" {
-#include "BKE_global.h"
-}
+struct ID;
+struct EvaluationContext;
struct DepsgraphStats;
struct DepsgraphStatsID;
struct DepsgraphStatsComponent;
-struct DepsgraphSettings;
-struct EvaluationContext;
-struct OperationDepsNode;
+
+namespace DEG {
struct Depsgraph;
+struct DepsgraphSettings;
+struct OperationDepsNode;
struct DepsgraphDebug {
static DepsgraphStats *stats;
@@ -77,11 +76,4 @@ struct DepsgraphDebug {
}
};
-#define DEG_DEBUG_PRINTF(...) \
- { \
- if (G.debug & G_DEBUG_DEPSGRAPH) { \
- fprintf(stderr, __VA_ARGS__); \
- } \
- } \
-
-#endif /* __DEPSGRAPH_DEBUG_H__ */
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
new file mode 100644
index 00000000000..af68f5c55c4
--- /dev/null
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -0,0 +1,224 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_tag.cc
+ * \ingroup depsgraph
+ *
+ * Core routines for how the Depsgraph works.
+ */
+
+#include "intern/eval/deg_eval_flush.h"
+
+// TODO(sergey): Use some sort of wrapper.
+#include <queue>
+
+extern "C" {
+#include "DNA_object_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_task.h"
+#include "BLI_ghash.h"
+
+#include "DEG_depsgraph.h"
+} /* extern "C" */
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+namespace {
+
+// TODO(sergey): De-duplicate with depsgraph_tag,cc
+void lib_id_recalc_tag(Main *bmain, ID *id)
+{
+ id->tag |= LIB_TAG_ID_RECALC;
+ DEG_id_type_tag(bmain, GS(id->name));
+}
+
+void lib_id_recalc_data_tag(Main *bmain, ID *id)
+{
+ id->tag |= LIB_TAG_ID_RECALC_DATA;
+ DEG_id_type_tag(bmain, GS(id->name));
+}
+
+} /* namespace */
+
+typedef std::queue<OperationDepsNode *> FlushQueue;
+
+static void flush_init_func(void *data_v, int i)
+{
+ /* ID node's done flag is used to avoid multiple editors update
+ * for the same ID.
+ */
+ Depsgraph *graph = (Depsgraph *)data_v;
+ OperationDepsNode *node = graph->operations[i];
+ IDDepsNode *id_node = node->owner->owner;
+ id_node->done = 0;
+ node->scheduled = false;
+ node->owner->flags &= ~DEPSCOMP_FULLY_SCHEDULED;
+}
+
+/* Flush updates from tagged nodes outwards until all affected nodes
+ * are tagged.
+ */
+void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
+{
+ /* Sanity check. */
+ if (graph == NULL) {
+ return;
+ }
+
+ /* Nothing to update, early out. */
+ if (BLI_gset_size(graph->entry_tags) == 0) {
+ return;
+ }
+
+ /* TODO(sergey): With a bit of flag magic we can get rid of this
+ * extra loop.
+ */
+ const int num_operations = graph->operations.size();
+ const bool do_threads = num_operations > 256;
+ BLI_task_parallel_range(0,
+ num_operations,
+ graph,
+ flush_init_func,
+ do_threads);
+
+ FlushQueue queue;
+ /* Starting from the tagged "entry" nodes, flush outwards... */
+ /* NOTE: Also need to ensure that for each of these, there is a path back to
+ * root, or else they won't be done.
+ * NOTE: Count how many nodes we need to handle - entry nodes may be
+ * component nodes which don't count for this purpose!
+ */
+ GSET_FOREACH_BEGIN(OperationDepsNode *, node, graph->entry_tags)
+ {
+ queue.push(node);
+ node->scheduled = true;
+ }
+ GSET_FOREACH_END();
+
+ while (!queue.empty()) {
+ OperationDepsNode *node = queue.front();
+ queue.pop();
+
+ for (;;) {
+ node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+
+ IDDepsNode *id_node = node->owner->owner;
+
+ if (id_node->done == 0) {
+ deg_editors_id_update(bmain, id_node->id);
+ id_node->done = 1;
+ }
+
+ lib_id_recalc_tag(bmain, id_node->id);
+ /* TODO(sergey): For until we've got proper data nodes in the graph. */
+ lib_id_recalc_data_tag(bmain, id_node->id);
+
+ ID *id = id_node->id;
+ /* This code is used to preserve those areas which does direct
+ * object update,
+ *
+ * Plus it ensures visibility changes and relations and layers
+ * visibility update has proper flags to work with.
+ */
+ if (GS(id->name) == ID_OB) {
+ Object *object = (Object *)id;
+ ComponentDepsNode *comp_node = node->owner;
+ if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
+ object->recalc |= OB_RECALC_TIME;
+ }
+ else if (comp_node->type == DEPSNODE_TYPE_TRANSFORM) {
+ object->recalc |= OB_RECALC_OB;
+ }
+ else {
+ object->recalc |= OB_RECALC_DATA;
+ }
+ }
+
+ /* TODO(sergey): For until incremental updates are possible
+ * witin a component at least we tag the whole component
+ * for update.
+ */
+ ComponentDepsNode *component = node->owner;
+ if ((component->flags & DEPSCOMP_FULLY_SCHEDULED) == 0) {
+ foreach (OperationDepsNode *op, component->operations) {
+ op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+ }
+ component->flags |= DEPSCOMP_FULLY_SCHEDULED;
+ }
+
+ /* Flush to nodes along links... */
+ if (node->outlinks.size() == 1) {
+ OperationDepsNode *to_node = (OperationDepsNode *)node->outlinks[0]->to;
+ if (to_node->scheduled == false) {
+ to_node->scheduled = true;
+ node = to_node;
+ }
+ else {
+ break;
+ }
+ }
+ else {
+ foreach (DepsRelation *rel, node->outlinks) {
+ OperationDepsNode *to_node = (OperationDepsNode *)rel->to;
+ if (to_node->scheduled == false) {
+ queue.push(to_node);
+ to_node->scheduled = true;
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
+static void graph_clear_func(void *data_v, int i)
+{
+ Depsgraph *graph = (Depsgraph *)data_v;
+ OperationDepsNode *node = graph->operations[i];
+ /* Clear node's "pending update" settings. */
+ node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE);
+}
+
+/* Clear tags from all operation nodes. */
+void deg_graph_clear_tags(Depsgraph *graph)
+{
+ /* Go over all operation nodes, clearing tags. */
+ const int num_operations = graph->operations.size();
+ const bool do_threads = num_operations > 256;
+ BLI_task_parallel_range(0, num_operations, graph, graph_clear_func, do_threads);
+ /* Clear any entry tags which haven't been flushed. */
+ BLI_gset_clear(graph->entry_tags, NULL);
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.h b/source/blender/depsgraph/intern/eval/deg_eval_flush.h
new file mode 100644
index 00000000000..8912aebee7d
--- /dev/null
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.h
@@ -0,0 +1,49 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): None Yet
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/eval/deg_eval_flush.cc
+ * \ingroup depsgraph
+ *
+ * Core routines for how the Depsgraph works.
+ */
+
+#pragma once
+
+struct Main;
+
+namespace DEG {
+
+struct Depsgraph;
+
+/* Flush updates from tagged nodes outwards until all affected nodes
+ * are tagged.
+ */
+void deg_graph_flush_updates(struct Main *bmain, struct Depsgraph *graph);
+
+/* Clear tags from all operation nodes. */
+void deg_graph_clear_tags(struct Depsgraph *graph);
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsnode.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc
index 8aa1059d2dc..78293f7f483 100644
--- a/source/blender/depsgraph/intern/depsnode.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node.cc
@@ -28,10 +28,13 @@
* \ingroup depsgraph
*/
+#include "intern/nodes/deg_node.h"
+
#include <stdio.h>
#include <string.h>
#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
extern "C" {
#include "DNA_ID.h"
@@ -42,10 +45,13 @@ extern "C" {
#include "DEG_depsgraph.h"
}
-#include "depsnode.h" /* own include */
-#include "depsnode_component.h"
-#include "depsnode_operation.h"
-#include "depsgraph_intern.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+#include "util/deg_util_hash.h"
+
+namespace DEG {
/* *************** */
/* Node Management */
@@ -66,7 +72,7 @@ DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type, const char *tname)
DepsNode::DepsNode()
{
- this->name[0] = '\0';
+ name[0] = '\0';
}
DepsNode::~DepsNode()
@@ -76,11 +82,9 @@ DepsNode::~DepsNode()
* when we're trying to free same link from both it's sides. We don't have
* dangling links so this is not a problem from memory leaks point of view.
*/
- DEPSNODE_RELATIONS_ITER_BEGIN(this->inlinks, rel)
- {
+ foreach (DepsRelation *rel, inlinks) {
OBJECT_GUARDED_DELETE(rel, DepsRelation);
}
- DEPSNODE_RELATIONS_ITER_END;
}
@@ -100,11 +104,7 @@ string DepsNode::identifier() const
void TimeSourceDepsNode::tag_update(Depsgraph *graph)
{
- for (DepsNode::Relations::const_iterator it = outlinks.begin();
- it != outlinks.end();
- ++it)
- {
- DepsRelation *rel = *it;
+ foreach (DepsRelation *rel, outlinks) {
DepsNode *node = rel->to;
node->tag_update(graph);
}
@@ -125,7 +125,7 @@ RootDepsNode::~RootDepsNode()
TimeSourceDepsNode *RootDepsNode::add_time_source(const string &name)
{
if (!time_source) {
- DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_TIMESOURCE);
+ DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_TIMESOURCE);
time_source = (TimeSourceDepsNode *)factory->create_node(NULL, "", name);
/*time_source->owner = this;*/ // XXX
}
@@ -142,6 +142,36 @@ static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE;
/* ID Node ================================================ */
+static unsigned int id_deps_node_hash_key(const void *key_v)
+{
+ const IDDepsNode::ComponentIDKey *key =
+ reinterpret_cast<const IDDepsNode::ComponentIDKey *>(key_v);
+ return hash_combine(BLI_ghashutil_uinthash(key->type),
+ BLI_ghashutil_strhash_p(key->name.c_str()));
+}
+
+static bool id_deps_node_hash_key_cmp(const void *a, const void *b)
+{
+ const IDDepsNode::ComponentIDKey *key_a =
+ reinterpret_cast<const IDDepsNode::ComponentIDKey *>(a);
+ const IDDepsNode::ComponentIDKey *key_b =
+ reinterpret_cast<const IDDepsNode::ComponentIDKey *>(b);
+ return !(*key_a == *key_b);
+}
+
+static void id_deps_node_hash_key_free(void *key_v)
+{
+ typedef IDDepsNode::ComponentIDKey ComponentIDKey;
+ ComponentIDKey *key = reinterpret_cast<ComponentIDKey *>(key_v);
+ OBJECT_GUARDED_DELETE(key, ComponentIDKey);
+}
+
+static void id_deps_node_hash_value_free(void *value_v)
+{
+ ComponentDepsNode *comp_node = reinterpret_cast<ComponentDepsNode *>(value_v);
+ OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode);
+}
+
/* Initialize 'id' node - from pointer data given. */
void IDDepsNode::init(const ID *id, const string &UNUSED(subdata))
{
@@ -151,6 +181,10 @@ void IDDepsNode::init(const ID *id, const string &UNUSED(subdata))
this->layers = (1 << 20) - 1;
this->eval_flags = 0;
+ components = BLI_ghash_new(id_deps_node_hash_key,
+ id_deps_node_hash_key_cmp,
+ "Depsgraph id components hash");
+
/* NOTE: components themselves are created if/when needed.
* This prevents problems with components getting added
* twice if an ID-Ref needs to be created to house it...
@@ -161,51 +195,27 @@ void IDDepsNode::init(const ID *id, const string &UNUSED(subdata))
IDDepsNode::~IDDepsNode()
{
clear_components();
-}
-
-/* Copy 'id' node. */
-void IDDepsNode::copy(DepsgraphCopyContext *dcc, const IDDepsNode *src)
-{
- (void)src; /* Ignored. */
- /* Iterate over items in original hash, adding them to new hash. */
- for (IDDepsNode::ComponentMap::const_iterator it = this->components.begin();
- it != this->components.end();
- ++it)
- {
- /* Get current <type : component> mapping. */
- ComponentIDKey c_key = it->first;
- DepsNode *old_component = it->second;
-
- /* Make a copy of component. */
- ComponentDepsNode *component = (ComponentDepsNode *)DEG_copy_node(dcc, old_component);
-
- /* Add new node to hash... */
- this->components[c_key] = component;
- }
-
- // TODO: perform a second loop to fix up links?
- BLI_assert(!"Not expected to be used");
+ BLI_ghash_free(components, id_deps_node_hash_key_free, NULL);
}
ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
const string &name) const
{
ComponentIDKey key(type, name);
- ComponentMap::const_iterator it = components.find(key);
- return it != components.end() ? it->second : NULL;
+ return reinterpret_cast<ComponentDepsNode *>(BLI_ghash_lookup(components, &key));
}
ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
const string &name)
{
- ComponentIDKey key(type, name);
ComponentDepsNode *comp_node = find_component(type, name);
if (!comp_node) {
- DepsNodeFactory *factory = DEG_get_node_factory(type);
+ DepsNodeFactory *factory = deg_get_node_factory(type);
comp_node = (ComponentDepsNode *)factory->create_node(this->id, "", name);
/* Register. */
- this->components[key] = comp_node;
+ ComponentIDKey *key = OBJECT_GUARDED_NEW(ComponentIDKey, type, name);
+ BLI_ghash_insert(components, key, comp_node);
comp_node->owner = this;
}
return comp_node;
@@ -213,34 +223,28 @@ ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
void IDDepsNode::remove_component(eDepsNode_Type type, const string &name)
{
- ComponentIDKey key(type, name);
ComponentDepsNode *comp_node = find_component(type, name);
if (comp_node) {
/* Unregister. */
- this->components.erase(key);
- OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode);
+ ComponentIDKey key(type, name);
+ BLI_ghash_remove(components,
+ &key,
+ id_deps_node_hash_key_free,
+ id_deps_node_hash_value_free);
}
}
void IDDepsNode::clear_components()
{
- for (ComponentMap::const_iterator it = components.begin();
- it != components.end();
- ++it)
- {
- ComponentDepsNode *comp_node = it->second;
- OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode);
- }
- components.clear();
+ BLI_ghash_clear(components,
+ id_deps_node_hash_key_free,
+ id_deps_node_hash_value_free);
}
void IDDepsNode::tag_update(Depsgraph *graph)
{
- for (ComponentMap::const_iterator it = components.begin();
- it != components.end();
- ++it)
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
{
- ComponentDepsNode *comp_node = it->second;
/* TODO(sergey): What about drievrs? */
bool do_component_tag = comp_node->type != DEPSNODE_TYPE_ANIMATION;
if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
@@ -254,6 +258,16 @@ void IDDepsNode::tag_update(Depsgraph *graph)
comp_node->tag_update(graph);
}
}
+ GHASH_FOREACH_END();
+}
+
+void IDDepsNode::finalize_build()
+{
+ GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, components)
+ {
+ comp_node->finalize_build();
+ }
+ GHASH_FOREACH_END();
}
DEG_DEPSNODE_DEFINE(IDDepsNode, DEPSNODE_TYPE_ID_REF, "ID Node");
@@ -281,31 +295,21 @@ SubgraphDepsNode::~SubgraphDepsNode()
// XXX: prune these flags a bit...
if ((this->flag & SUBGRAPH_FLAG_FIRSTREF) || !(this->flag & SUBGRAPH_FLAG_SHARED)) {
/* Free the referenced graph. */
- DEG_graph_free(this->graph);
- this->graph = NULL;
+ DEG_graph_free(reinterpret_cast< ::Depsgraph* >(graph));
+ graph = NULL;
}
}
-/* Copy 'subgraph' node - Assume that the subgraph doesn't get copied for now... */
-void SubgraphDepsNode::copy(DepsgraphCopyContext * /*dcc*/,
- const SubgraphDepsNode * /*src*/)
-{
- //const SubgraphDepsNode *src_node = (const SubgraphDepsNode *)src;
- //SubgraphDepsNode *dst_node = (SubgraphDepsNode *)dst;
-
- /* for now, subgraph itself isn't copied... */
- BLI_assert(!"Not expected to be used");
-}
-
DEG_DEPSNODE_DEFINE(SubgraphDepsNode, DEPSNODE_TYPE_SUBGRAPH, "Subgraph Node");
static DepsNodeFactoryImpl<SubgraphDepsNode> DNTI_SUBGRAPH;
-
-void DEG_register_base_depsnodes()
+void deg_register_base_depsnodes()
{
- DEG_register_node_typeinfo(&DNTI_ROOT);
- DEG_register_node_typeinfo(&DNTI_TIMESOURCE);
+ deg_register_node_typeinfo(&DNTI_ROOT);
+ deg_register_node_typeinfo(&DNTI_TIMESOURCE);
- DEG_register_node_typeinfo(&DNTI_ID_REF);
- DEG_register_node_typeinfo(&DNTI_SUBGRAPH);
+ deg_register_node_typeinfo(&DNTI_ID_REF);
+ deg_register_node_typeinfo(&DNTI_SUBGRAPH);
}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsnode.h b/source/blender/depsgraph/intern/nodes/deg_node.h
index 4a464955384..d79d3d2348d 100644
--- a/source/blender/depsgraph/intern/depsnode.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node.h
@@ -28,21 +28,18 @@
* \ingroup depsgraph
*/
-#ifndef __DEPSNODE_H__
-#define __DEPSNODE_H__
+#pragma once
-#include "depsgraph_types.h"
-
-#include "depsgraph_util_hash.h"
-#include "depsgraph_util_map.h"
-#include "depsgraph_util_set.h"
+#include "intern/depsgraph_types.h"
struct ID;
+struct GHash;
struct Scene;
+namespace DEG {
+
struct Depsgraph;
struct DepsRelation;
-struct DepsgraphCopyContext;
struct OperationDepsNode;
/* *********************************** */
@@ -94,8 +91,6 @@ struct DepsNode {
virtual void init(const ID * /*id*/,
const string &/*subdata*/) {}
- virtual void copy(DepsgraphCopyContext * /*dcc*/,
- const DepsNode * /*src*/) {}
virtual void tag_update(Depsgraph * /*graph*/) {}
@@ -160,24 +155,7 @@ struct IDDepsNode : public DepsNode {
string name;
};
- /* XXX can't specialize std::hash for this purpose, because ComponentIDKey is
- * a nested type ...
- *
- * http://stackoverflow.com/a/951245
- */
- struct component_key_hash {
- bool operator() (const ComponentIDKey &key) const
- {
- return hash_combine(hash<int>()(key.type), hash<string>()(key.name));
- }
- };
-
- typedef unordered_map<ComponentIDKey,
- ComponentDepsNode *,
- component_key_hash> ComponentMap;
-
void init(const ID *id, const string &subdata);
- void copy(DepsgraphCopyContext *dcc, const IDDepsNode *src);
~IDDepsNode();
ComponentDepsNode *find_component(eDepsNode_Type type,
@@ -189,11 +167,13 @@ struct IDDepsNode : public DepsNode {
void tag_update(Depsgraph *graph);
+ void finalize_build();
+
/* ID Block referenced. */
ID *id;
/* Hash to make it faster to look up components. */
- ComponentMap components;
+ GHash *components;
/* Layers of this node with accumulated layers of it's output relations. */
int layers;
@@ -210,7 +190,6 @@ struct IDDepsNode : public DepsNode {
/* Subgraph Reference. */
struct SubgraphDepsNode : public DepsNode {
void init(const ID *id, const string &subdata);
- void copy(DepsgraphCopyContext *dcc, const SubgraphDepsNode *src);
~SubgraphDepsNode();
/* Instanced graph. */
@@ -243,6 +222,6 @@ typedef enum eSubgraphRef_Flag {
SUBGRAPH_FLAG_FIRSTREF = (1 << 1),
} eSubgraphRef_Flag;
-void DEG_register_base_depsnodes();
+void deg_register_base_depsnodes();
-#endif /* __DEPSNODE_H__ */
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsnode_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
index a47a0d29228..7e49fec051f 100644
--- a/source/blender/depsgraph/intern/depsnode_component.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
@@ -28,6 +28,8 @@
* \ingroup depsgraph
*/
+#include "intern/nodes/deg_node_component.h"
+
#include <stdio.h>
#include <string.h>
@@ -39,20 +41,57 @@ extern "C" {
#include "BKE_action.h"
} /* extern "C" */
-#include "depsnode_component.h" /* own include */
-#include "depsnode_operation.h"
-#include "depsgraph_intern.h"
+#include "intern/nodes/deg_node_operation.h"
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+#include "util/deg_util_hash.h"
+
+namespace DEG {
/* *********** */
/* Outer Nodes */
/* Standard Component Methods ============================= */
+static unsigned int comp_node_hash_key(const void *key_v)
+{
+ const ComponentDepsNode::OperationIDKey *key =
+ reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(key_v);
+ return hash_combine(BLI_ghashutil_uinthash(key->opcode),
+ BLI_ghashutil_strhash_p(key->name.c_str()));
+}
+
+static bool comp_node_hash_key_cmp(const void *a, const void *b)
+{
+ const ComponentDepsNode::OperationIDKey *key_a =
+ reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(a);
+ const ComponentDepsNode::OperationIDKey *key_b =
+ reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(b);
+ return !(*key_a == *key_b);
+}
+
+static void comp_node_hash_key_free(void *key_v)
+{
+ typedef ComponentDepsNode::OperationIDKey OperationIDKey;
+ OperationIDKey *key = reinterpret_cast<OperationIDKey *>(key_v);
+ OBJECT_GUARDED_DELETE(key, OperationIDKey);
+}
+
+static void comp_node_hash_value_free(void *value_v)
+{
+ OperationDepsNode *op_node = reinterpret_cast<OperationDepsNode *>(value_v);
+ OBJECT_GUARDED_DELETE(op_node, OperationDepsNode);
+}
+
ComponentDepsNode::ComponentDepsNode() :
entry_operation(NULL),
exit_operation(NULL),
- flags(0)
+ flags(0),
+ layers(0)
{
+ operations_map = BLI_ghash_new(comp_node_hash_key,
+ comp_node_hash_key_cmp,
+ "Depsgraph id hash");
}
/* Initialize 'component' node - from pointer data given */
@@ -63,37 +102,15 @@ void ComponentDepsNode::init(const ID * /*id*/,
// XXX: maybe this needs a special API?
}
-/* Copy 'component' node */
-void ComponentDepsNode::copy(DepsgraphCopyContext * /*dcc*/,
- const ComponentDepsNode * /*src*/)
-{
-#if 0 // XXX: remove all this
- /* duplicate list of operation nodes */
- this->operations.clear();
-
- for (OperationMap::const_iterator it = src->operations.begin(); it != src->operations.end(); ++it) {
- const string &pchan_name = it->first;
- OperationDepsNode *src_op = it->second;
-
- /* recursive copy */
- DepsNodeFactory *factory = DEG_node_get_factory(src_op);
- OperationDepsNode *dst_op = (OperationDepsNode *)factory->copy_node(dcc, src_op);
- this->operations[pchan_name] = dst_op;
-
- /* fix links... */
- // ...
- }
-
- /* copy evaluation contexts */
- //
-#endif
- BLI_assert(!"Not expected to be called");
-}
-
/* Free 'component' node */
ComponentDepsNode::~ComponentDepsNode()
{
clear_operations();
+ if (operations_map != NULL) {
+ BLI_ghash_free(operations_map,
+ comp_node_hash_key_free,
+ comp_node_hash_value_free);
+ }
}
string ComponentDepsNode::identifier() const
@@ -103,15 +120,17 @@ string ComponentDepsNode::identifier() const
char typebuf[7];
sprintf(typebuf, "(%d)", type);
- return string(typebuf) + name + " : " + idname;
+ char layers[7];
+ sprintf(layers, "%d", this->layers);
+
+ return string(typebuf) + name + " : " + idname + " (Layers: " + layers + ")";
}
OperationDepsNode *ComponentDepsNode::find_operation(OperationIDKey key) const
{
- OperationMap::const_iterator it = this->operations.find(key);
-
- if (it != this->operations.end()) {
- return it->second;
+ OperationDepsNode *node = reinterpret_cast<OperationDepsNode *>(BLI_ghash_lookup(operations_map, &key));
+ if (node != NULL) {
+ return node;
}
else {
fprintf(stderr, "%s: find_operation(%s) failed\n",
@@ -129,11 +148,7 @@ OperationDepsNode *ComponentDepsNode::find_operation(eDepsOperation_Code opcode,
OperationDepsNode *ComponentDepsNode::has_operation(OperationIDKey key) const
{
- OperationMap::const_iterator it = this->operations.find(key);
- if (it != this->operations.end()) {
- return it->second;
- }
- return NULL;
+ return reinterpret_cast<OperationDepsNode *>(BLI_ghash_lookup(operations_map, &key));
}
OperationDepsNode *ComponentDepsNode::has_operation(eDepsOperation_Code opcode,
@@ -147,12 +162,12 @@ OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype,
{
OperationDepsNode *op_node = has_operation(opcode, name);
if (!op_node) {
- DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_OPERATION);
+ DepsNodeFactory *factory = deg_get_node_factory(DEPSNODE_TYPE_OPERATION);
op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name);
/* register opnode in this component's operation set */
- OperationIDKey key(opcode, name);
- this->operations[key] = op_node;
+ OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name);
+ BLI_ghash_insert(operations_map, key, op_node);
/* set as entry/exit node of component (if appropriate) */
if (optype == DEPSOP_TYPE_INIT) {
@@ -185,18 +200,22 @@ OperationDepsNode *ComponentDepsNode::add_operation(eDepsOperation_Type optype,
void ComponentDepsNode::remove_operation(eDepsOperation_Code opcode, const string &name)
{
- OperationDepsNode *op_node = find_operation(opcode, name);
- if (op_node) {
- /* unregister */
- this->operations.erase(OperationIDKey(opcode, name));
- OBJECT_GUARDED_DELETE(op_node, OperationDepsNode);
- }
+ /* unregister */
+ OperationIDKey key(opcode, name);
+ BLI_ghash_remove(operations_map,
+ &key,
+ comp_node_hash_key_free,
+ comp_node_hash_key_free);
}
void ComponentDepsNode::clear_operations()
{
- for (OperationMap::const_iterator it = operations.begin(); it != operations.end(); ++it) {
- OperationDepsNode *op_node = it->second;
+ if (operations_map != NULL) {
+ BLI_ghash_clear(operations_map,
+ comp_node_hash_key_free,
+ comp_node_hash_value_free);
+ }
+ foreach (OperationDepsNode *op_node, operations) {
OBJECT_GUARDED_DELETE(op_node, OperationDepsNode);
}
operations.clear();
@@ -208,30 +227,79 @@ void ComponentDepsNode::tag_update(Depsgraph *graph)
if (entry_op != NULL && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
return;
}
- for (OperationMap::const_iterator it = operations.begin(); it != operations.end(); ++it) {
- OperationDepsNode *op_node = it->second;
+ foreach (OperationDepsNode *op_node, operations) {
op_node->tag_update(graph);
}
+ // It is possible that tag happens before finalization.
+ if (operations_map != NULL) {
+ GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, operations_map)
+ {
+ op_node->tag_update(graph);
+ }
+ GHASH_FOREACH_END();
+ }
}
OperationDepsNode *ComponentDepsNode::get_entry_operation()
{
- if (entry_operation)
+ if (entry_operation) {
return entry_operation;
- else if (operations.size() == 1)
- return operations.begin()->second;
+ }
+ else if (operations_map != NULL && BLI_ghash_size(operations_map) == 1) {
+ OperationDepsNode *op_node = NULL;
+ /* TODO(sergey): This is somewhat slow. */
+ GHASH_FOREACH_BEGIN(OperationDepsNode *, tmp, operations_map)
+ {
+ op_node = tmp;
+ }
+ GHASH_FOREACH_END();
+ /* Cache for the subsequent usage. */
+ entry_operation = op_node;
+ return op_node;
+ }
+ else if(operations.size() == 1) {
+ return operations[0];
+ }
return NULL;
}
OperationDepsNode *ComponentDepsNode::get_exit_operation()
{
- if (exit_operation)
+ if (exit_operation) {
return exit_operation;
- else if (operations.size() == 1)
- return operations.begin()->second;
+ }
+ else if (operations_map != NULL && BLI_ghash_size(operations_map) == 1) {
+ OperationDepsNode *op_node = NULL;
+ /* TODO(sergey): This is somewhat slow. */
+ GHASH_FOREACH_BEGIN(OperationDepsNode *, tmp, operations_map)
+ {
+ op_node = tmp;
+ }
+ GHASH_FOREACH_END();
+ /* Cache for the subsequent usage. */
+ exit_operation = op_node;
+ return op_node;
+ }
+ else if(operations.size() == 1) {
+ return operations[0];
+ }
return NULL;
}
+void ComponentDepsNode::finalize_build()
+{
+ operations.reserve(BLI_ghash_size(operations_map));
+ GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, operations_map)
+ {
+ operations.push_back(op_node);
+ }
+ GHASH_FOREACH_END();
+ BLI_ghash_free(operations_map,
+ comp_node_hash_key_free,
+ NULL);
+ operations_map = NULL;
+}
+
/* Parameter Component Defines ============================ */
DEG_DEPSNODE_DEFINE(ParametersComponentDepsNode, DEPSNODE_TYPE_PARAMETERS, "Parameters Component");
@@ -302,18 +370,20 @@ static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING;
/* Node Types Register =================================== */
-void DEG_register_component_depsnodes()
+void deg_register_component_depsnodes()
{
- DEG_register_node_typeinfo(&DNTI_PARAMETERS);
- DEG_register_node_typeinfo(&DNTI_PROXY);
- DEG_register_node_typeinfo(&DNTI_ANIMATION);
- DEG_register_node_typeinfo(&DNTI_TRANSFORM);
- DEG_register_node_typeinfo(&DNTI_GEOMETRY);
- DEG_register_node_typeinfo(&DNTI_SEQUENCER);
-
- DEG_register_node_typeinfo(&DNTI_EVAL_POSE);
- DEG_register_node_typeinfo(&DNTI_BONE);
-
- DEG_register_node_typeinfo(&DNTI_EVAL_PARTICLES);
- DEG_register_node_typeinfo(&DNTI_SHADING);
+ deg_register_node_typeinfo(&DNTI_PARAMETERS);
+ deg_register_node_typeinfo(&DNTI_PROXY);
+ deg_register_node_typeinfo(&DNTI_ANIMATION);
+ deg_register_node_typeinfo(&DNTI_TRANSFORM);
+ deg_register_node_typeinfo(&DNTI_GEOMETRY);
+ deg_register_node_typeinfo(&DNTI_SEQUENCER);
+
+ deg_register_node_typeinfo(&DNTI_EVAL_POSE);
+ deg_register_node_typeinfo(&DNTI_BONE);
+
+ deg_register_node_typeinfo(&DNTI_EVAL_PARTICLES);
+ deg_register_node_typeinfo(&DNTI_SHADING);
}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsnode_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h
index 7f44c0ed03f..df321ea9299 100644
--- a/source/blender/depsgraph/intern/depsnode_component.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h
@@ -28,21 +28,22 @@
* \ingroup depsgraph
*/
-#ifndef __DEPSNODE_COMPONENT_H__
-#define __DEPSNODE_COMPONENT_H__
+#pragma once
-#include "depsnode.h"
+#include "intern/nodes/deg_node.h"
-#include "depsgraph_util_hash.h"
-#include "depsgraph_util_map.h"
-#include "depsgraph_util_set.h"
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
struct ID;
struct bPoseChannel;
+struct GHash;
-struct Depsgraph;
-struct DepsgraphCopyContext;
struct EvaluationContext;
+
+namespace DEG {
+
+struct Depsgraph;
struct OperationDepsNode;
struct BoneComponentDepsNode;
@@ -75,7 +76,7 @@ struct ComponentDepsNode : public DepsNode {
string identifier() const
{
char codebuf[5];
- sprintf(codebuf, "%d", opcode);
+ BLI_snprintf(codebuf, sizeof(codebuf), "%d", opcode);
return string("OperationIDKey(") + codebuf + ", " + name + ")";
}
@@ -86,47 +87,41 @@ struct ComponentDepsNode : public DepsNode {
}
};
- /* XXX can't specialize std::hash for this purpose, because ComponentKey is a nested type ...
- * http://stackoverflow.com/a/951245
- */
- struct operation_key_hash {
- bool operator() (const OperationIDKey &key) const
- {
- return hash_combine(hash<int>()(key.opcode), hash<string>()(key.name));
- }
- };
-
/* Typedef for container of operations */
- typedef unordered_map<OperationIDKey, OperationDepsNode *, operation_key_hash> OperationMap;
-
-
ComponentDepsNode();
~ComponentDepsNode();
void init(const ID *id, const string &subdata);
- void copy(DepsgraphCopyContext *dcc, const ComponentDepsNode *src);
string identifier() const;
/* Find an existing operation, will throw an assert() if it does not exist. */
OperationDepsNode *find_operation(OperationIDKey key) const;
- OperationDepsNode *find_operation(eDepsOperation_Code opcode, const string &name) const;
+ OperationDepsNode *find_operation(eDepsOperation_Code opcode,
+ const string &name) const;
/* Check operation exists and return it. */
OperationDepsNode *has_operation(OperationIDKey key) const;
- OperationDepsNode *has_operation(eDepsOperation_Code opcode, const string &name) const;
+ OperationDepsNode *has_operation(eDepsOperation_Code opcode,
+ const string &name) const;
/**
* Create a new node for representing an operation and add this to graph
- * \warning If an existing node is found, it will be modified. This helps when node may
- * have been partially created earlier (e.g. parent ref before parent item is added)
+ * \warning If an existing node is found, it will be modified. This helps
+ * when node may have been partially created earlier (e.g. parent ref before
+ * parent item is added)
*
- * \param type: Operation node type (corresponding to context/component that it operates in)
- * \param optype: Role that operation plays within component (i.e. where in eval process)
+ * \param type: Operation node type (corresponding to context/component that
+ * it operates in)
+ * \param optype: Role that operation plays within component
+ * (i.e. where in eval process)
* \param op: The operation to perform
* \param name: Identifier for operation - used to find/locate it again
*/
- OperationDepsNode *add_operation(eDepsOperation_Type optype, DepsEvalOperationCb op, eDepsOperation_Code opcode, const string &name);
+ OperationDepsNode *add_operation(eDepsOperation_Type optype,
+ DepsEvalOperationCb op,
+ eDepsOperation_Code opcode,
+ const string &name);
void remove_operation(eDepsOperation_Code opcode, const string &name);
void clear_operations();
@@ -135,9 +130,13 @@ struct ComponentDepsNode : public DepsNode {
/* Evaluation Context Management .................. */
- /* Initialize component's evaluation context used for the specified purpose */
+ /* Initialize component's evaluation context used for the specified
+ * purpose.
+ */
virtual bool eval_context_init(EvaluationContext * /*eval_ctx*/) { return false; }
- /* Free data in component's evaluation context which is used for the specified purpose
+ /* Free data in component's evaluation context which is used for
+ * the specified purpose
+ *
* NOTE: this does not free the actual context in question
*/
virtual void eval_context_free(EvaluationContext * /*eval_ctx*/) {}
@@ -145,15 +144,31 @@ struct ComponentDepsNode : public DepsNode {
OperationDepsNode *get_entry_operation();
OperationDepsNode *get_exit_operation();
+ void finalize_build();
+
IDDepsNode *owner;
- OperationMap operations; /* inner nodes for this component */
+ /* ** Inner nodes for this component ** */
+
+ /* Operations stored as a hash map, for faster build.
+ * This hash map will be freed when graph is fully built.
+ */
+ GHash *operations_map;
+
+ /* This is a "normal" list of operations, used by evaluation
+ * and other routines after construction.
+ */
+ vector<OperationDepsNode *> operations;
+
OperationDepsNode *entry_operation;
OperationDepsNode *exit_operation;
// XXX: a poll() callback to check if component's first node can be started?
int flags;
+
+ /* Temporary bitmask, used during graph construction. */
+ int layers;
};
/* ---------------------------------------- */
@@ -204,6 +219,6 @@ struct ShadingComponentDepsNode : public ComponentDepsNode {
};
-void DEG_register_component_depsnodes();
+void deg_register_component_depsnodes();
-#endif /* __DEPSNODE_COMPONENT_H__ */
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsnode_operation.cc b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
index 6aeb163356b..a9f9703bb3b 100644
--- a/source/blender/depsgraph/intern/depsnode_operation.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.cc
@@ -28,35 +28,27 @@
* \ingroup depsgraph
*/
+#include "intern/nodes/deg_node_operation.h"
+
#include "MEM_guardedalloc.h"
extern "C" {
#include "BLI_utildefines.h"
} /* extern "C" */
-#include "depsnode_operation.h" /* own include */
-#include "depsnode_component.h"
-#include "depsgraph.h"
-#include "depsgraph_intern.h"
-
-/* ******************************************************************* */
-/* OpNode Identifiers Array - Exported to other depsgraph files too... */
+#include "intern/depsgraph.h"
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_hash.h"
-/* identifiers for operations */
-const char *DEG_OPNAMES[] = {
-#define DEF_DEG_OPCODE(label) #label,
-#include "depsnode_opcodes.h"
-#undef DEF_DEG_OPCODE
-
- "<Invalid>"
-};
+namespace DEG {
/* *********** */
/* Inner Nodes */
OperationDepsNode::OperationDepsNode() :
eval_priority(0.0f),
- flag(0)
+ flag(0),
+ customdata_mask(0)
{
}
@@ -66,7 +58,6 @@ OperationDepsNode::~OperationDepsNode()
string OperationDepsNode::identifier() const
{
- BLI_assert((opcode > 0) && (opcode < ARRAY_SIZE(DEG_OPNAMES)));
return string(DEG_OPNAMES[opcode]) + "(" + name + ")";
}
@@ -98,7 +89,9 @@ void OperationDepsNode::tag_update(Depsgraph *graph)
DEG_DEPSNODE_DEFINE(OperationDepsNode, DEPSNODE_TYPE_OPERATION, "Operation");
static DepsNodeFactoryImpl<OperationDepsNode> DNTI_OPERATION;
-void DEG_register_operation_depsnodes()
+void deg_register_operation_depsnodes()
{
- DEG_register_node_typeinfo(&DNTI_OPERATION);
+ deg_register_node_typeinfo(&DNTI_OPERATION);
}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsnode_operation.h b/source/blender/depsgraph/intern/nodes/deg_node_operation.h
index 1119e10805d..f03078fc3db 100644
--- a/source/blender/depsgraph/intern/depsnode_operation.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_operation.h
@@ -28,15 +28,15 @@
* \ingroup depsgraph
*/
-#ifndef __DEPSNODE_OPERATION_H__
-#define __DEPSNODE_OPERATION_H__
+#pragma once
-#include "depsnode.h"
+#include "intern/nodes/deg_node.h"
struct ID;
struct Depsgraph;
-struct DepsgraphCopyContext;
+
+namespace DEG {
/* Flags for Depsgraph Nodes */
typedef enum eDepsOperation_Flag {
@@ -44,10 +44,14 @@ typedef enum eDepsOperation_Flag {
DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0),
/* node was directly modified, causing need for update */
- /* XXX: intention is to make it easier to tell when we just need to take subgraphs */
+ /* XXX: intention is to make it easier to tell when we just need to
+ * take subgraphs.
+ */
DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1),
- /* Operation is evaluated using CPython; has GIL and security implications... */
+ /* Operation is evaluated using CPython; has GIL and security
+ * implications...
+ */
DEPSOP_FLAG_USES_PYTHON = (1 << 2),
} eDepsOperation_Flag;
@@ -68,23 +72,33 @@ struct OperationDepsNode : public DepsNode {
OperationDepsNode *get_entry_operation() { return this; }
OperationDepsNode *get_exit_operation() { return this; }
- ComponentDepsNode *owner; /* component that contains the operation */
+ /* Component that contains the operation. */
+ ComponentDepsNode *owner;
- DepsEvalOperationCb evaluate; /* callback for operation */
+ /* Callback for operation. */
+ DepsEvalOperationCb evaluate;
- uint32_t num_links_pending; /* how many inlinks are we still waiting on before we can be evaluated... */
+ /* How many inlinks are we still waiting on before we can be evaluated. */
+ uint32_t num_links_pending;
float eval_priority;
bool scheduled;
- short optype; /* (eDepsOperation_Type) stage of evaluation */
- int opcode; /* (eDepsOperation_Code) identifier for the operation being performed */
+ /* Stage of evaluation */
+ eDepsOperation_Type optype;
+
+ /* Identifier for the operation being performed. */
+ eDepsOperation_Code opcode;
+
+ /* (eDepsOperation_Flag) extra settings affecting evaluation. */
+ int flag;
- int flag; /* (eDepsOperation_Flag) extra settings affecting evaluation */
+ /* Extra customdata mask which needs to be evaluated for the object. */
+ uint64_t customdata_mask;
DEG_DEPSNODE_DECLARE;
};
-void DEG_register_operation_depsnodes();
+void deg_register_operation_depsnodes();
-#endif /* __DEPSNODE_OPERATION_H__ */
+} // namespace DEG
diff --git a/source/blender/depsgraph/util/deg_util_foreach.h b/source/blender/depsgraph/util/deg_util_foreach.h
new file mode 100644
index 00000000000..14cf4fc11ed
--- /dev/null
+++ b/source/blender/depsgraph/util/deg_util_foreach.h
@@ -0,0 +1,68 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Sergey Sharybin
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/util/deg_util_foreach.h
+ * \ingroup depsgraph
+ */
+
+#pragma once
+
+#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)
+# define foreach(x, y) for(x : y)
+#elif defined(HAVE_BOOST_FUNCTION_BINDINGS)
+# include <boost/foreach.hpp>
+# define foreach BOOST_FOREACH
+#else
+#pragma message("No available foreach() implementation. Using stub instead, disabling new depsgraph")
+
+#ifndef WITH_LEGACY_DEPSGRAPH
+# error "Unable to build new depsgraph and legacy one is disabled."
+#endif
+
+#define DISABLE_NEW_DEPSGRAPH
+
+# define foreach(x, y) for (x; false; (void)y)
+#endif
+
+#define GHASH_FOREACH_BEGIN(type, var, what) \
+ do { \
+ GHashIterator gh_iter##var; \
+ GHASH_ITER(gh_iter##var, what) { \
+ type var = reinterpret_cast<type>(BLI_ghashIterator_getValue(&gh_iter##var)); \
+
+#define GHASH_FOREACH_END() \
+ } \
+ } while(0)
+
+#define GSET_FOREACH_BEGIN(type, var, what) \
+ do { \
+ GSetIterator gh_iter##var; \
+ GSET_ITER(gh_iter##var, what) { \
+ type var = reinterpret_cast<type>(BLI_gsetIterator_getKey(&gh_iter##var)); \
+
+#define GSET_FOREACH_END() \
+ } \
+ } while(0)
diff --git a/source/blender/depsgraph/util/depsgraph_util_function.h b/source/blender/depsgraph/util/deg_util_function.h
index a4301833408..1e34ae04d9a 100644
--- a/source/blender/depsgraph/util/depsgraph_util_function.h
+++ b/source/blender/depsgraph/util/deg_util_function.h
@@ -24,12 +24,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/util/depsgraph_util_function.h
+/** \file blender/depsgraph/util/deg_util_function.h
* \ingroup depsgraph
*/
-#ifndef __DEPSGRAPH_UTIL_FUNCTION_H__
-#define __DEPSGRAPH_UTIL_FUNCTION_H__
+#pragma once
#if (__cplusplus > 199711L)
@@ -57,6 +56,7 @@ using boost::function;
#define DISABLE_NEW_DEPSGRAPH
+#include "BLI_utildefines.h"
#include <cstdlib>
template<typename T>
@@ -108,5 +108,3 @@ void *function_bind(T func,
#define _4 Wrap()
#endif
-
-#endif /* __DEPSGRAPH_UTIL_FUNCTION_H__ */
diff --git a/source/blender/depsgraph/util/depsgraph_util_set.h b/source/blender/depsgraph/util/deg_util_hash.h
index 008ec6b74ca..e490be1a7a1 100644
--- a/source/blender/depsgraph/util/depsgraph_util_set.h
+++ b/source/blender/depsgraph/util/deg_util_hash.h
@@ -24,43 +24,18 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/depsgraph/util/depsgraph_util_set.h
+/** \file blender/depsgraph/util/deg_util_hash.h
* \ingroup depsgraph
*/
-#ifndef __DEPSGRAPH_UTIL_SET_H__
-#define __DEPSGRAPH_UTIL_SET_H__
+#pragma once
-#include <set>
+#include "BLI_utildefines.h"
-#include "depsgraph_util_hash.h"
+#include "BLI_ghash.h"
-using std::set;
-
-#if defined(DEG_NO_UNORDERED_MAP)
-# include <set>
-typedef std::set unordered_set;
-#endif
-
-#if defined(DEG_TR1_UNORDERED_MAP)
-# include <tr1/unordered_set>
-using std::tr1::unordered_set;
-#endif
-
-#if defined(DEG_STD_UNORDERED_MAP)
-# include <unordered_set>
-using std::unordered_set;
-#endif
-
-#if defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
-# include <unordered_set>
-using std::tr1::unordered_set;
-#endif
-
-#if !defined(DEG_NO_UNORDERED_MAP) && !defined(DEG_TR1_UNORDERED_MAP) && \
- !defined(DEG_STD_UNORDERED_MAP) && !defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT
-# error One of: DEG_NO_UNORDERED_MAP, DEG_TR1_UNORDERED_MAP,\
- DEG_STD_UNORDERED_MAP, DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT
-#endif
-
-#endif /* __DEPSGRAPH_UTIL_SET_H__ */
+/* XXX this might require 2 different variants for sizeof(size_t) (32 vs 64 bit) */
+BLI_INLINE size_t hash_combine(size_t hash_a, size_t hash_b)
+{
+ return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
+}
diff --git a/source/blender/depsgraph/util/depsgraph_util_hash.h b/source/blender/depsgraph/util/depsgraph_util_hash.h
deleted file mode 100644
index bc75627a026..00000000000
--- a/source/blender/depsgraph/util/depsgraph_util_hash.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- *
- * Original Author: Brecht van Lommel
- * Contributor(s): Lukas Toenne
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/depsgraph/util/depsgraph_util_hash.h
- * \ingroup depsgraph
- */
-
-#ifndef __DEPSGRAPH_UTIL_HASH_H__
-#define __DEPSGRAPH_UTIL_HASH_H__
-
-#if defined(DEG_NO_UNORDERED_MAP)
-# define DEG_HASH_NAMESPACE_BEGIN
-# define DEG_HASH_NAMESPACE_END
-#endif
-
-#if defined(DEG_TR1_UNORDERED_MAP)
-# include <tr1/unordered_map>
-# define DEG_HASH_NAMESPACE_BEGIN namespace std { namespace tr1 {
-# define DEG_HASH_NAMESPACE_END } }
-using std::tr1::hash;
-#endif
-
-#if defined(DEG_STD_UNORDERED_MAP)
-# include <unordered_map>
-# define DEG_HASH_NAMESPACE_BEGIN namespace std {
-# define DEG_HASH_NAMESPACE_END }
-using std::hash;
-#endif
-
-#if defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
-# include <unordered_map>
-# define DEG_HASH_NAMESPACE_BEGIN namespace std { namespace tr1 {
-# define DEG_HASH_NAMESPACE_END } }
-using std::tr1::hash;
-#endif
-
-#if !defined(DEG_NO_UNORDERED_MAP) && !defined(DEG_TR1_UNORDERED_MAP) && \
- !defined(DEG_STD_UNORDERED_MAP) && !defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT
-# error One of: DEG_NO_UNORDERED_MAP, DEG_TR1_UNORDERED_MAP,\
- DEG_STD_UNORDERED_MAP, DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT
-#endif
-
-/* XXX this might require 2 different variants for sizeof(size_t) (32 vs 64 bit) */
-inline size_t hash_combine(size_t hash_a, size_t hash_b)
-{
- return hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2));
-}
-
-#endif /* __DEPSGRAPH_UTIL_HASH_H__ */
diff --git a/source/blender/depsgraph/util/depsgraph_util_map.h b/source/blender/depsgraph/util/depsgraph_util_map.h
deleted file mode 100644
index 0eae1d79e34..00000000000
--- a/source/blender/depsgraph/util/depsgraph_util_map.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2014 Blender Foundation.
- * All rights reserved.
- *
- * Original Author: Brecht van Lommel
- * Contributor(s): Lukas Toenne
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/depsgraph/util/depsgraph_util_map.h
- * \ingroup depsgraph
- */
-
-#ifndef __DEPSGRAPH_UTIL_MAP_H__
-#define __DEPSGRAPH_UTIL_MAP_H__
-
-#include <map>
-
-#include "depsgraph_util_hash.h"
-
-using std::map;
-using std::pair;
-
-#if defined(DEG_NO_UNORDERED_MAP)
-# include <map>
-typedef std::map unordered_map;
-#endif
-
-#if defined(DEG_TR1_UNORDERED_MAP)
-# include <tr1/unordered_map>
-using std::tr1::unordered_map;
-#endif
-
-#if defined(DEG_STD_UNORDERED_MAP)
-# include <unordered_map>
-using std::unordered_map;
-#endif
-
-#if defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE)
-# include <unordered_map>
-using std::tr1::unordered_map;
-#endif
-
-#if !defined(DEG_NO_UNORDERED_MAP) && !defined(DEG_TR1_UNORDERED_MAP) && \
- !defined(DEG_STD_UNORDERED_MAP) && !defined(DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE) // NOLINT
-# error One of: DEG_NO_UNORDERED_MAP, DEG_TR1_UNORDERED_MAP,\
- DEG_STD_UNORDERED_MAP, DEG_STD_UNORDERED_MAP_IN_TR1_NAMESPACE must be defined! // NOLINT
-#endif
-
-#endif /* __DEPSGRAPH_UTIL_MAP_H__ */
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index 5665ce59783..437dd2b2de2 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -399,7 +399,13 @@ void ANIM_animdata_update(bAnimContext *ac, ListBase *anim_data)
ANIM_list_elem_update(ac->scene, ale);
}
}
-
+ else if (ale->datatype == ALE_NLASTRIP) {
+ if (ale->update & ANIM_UPDATE_DEPS) {
+ ale->update &= ~ANIM_UPDATE_DEPS;
+ ANIM_list_elem_update(ac->scene, ale);
+ }
+ }
+
BLI_assert(ale->update == 0);
}
}
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index afc4e5c9e61..51f962d4a1e 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -866,7 +866,7 @@ static int add_driver_button_exec(bContext *C, wmOperator *op)
}
/* Show menu or create drivers */
-static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
PropertyRNA *prop;
@@ -877,7 +877,8 @@ static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *
else {
/* Show menu */
// TODO: This should get filtered by the enum filter
- return WM_menu_invoke(C, op, event);
+ /* important to execute in the region we're currently in */
+ return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_DEFAULT);
}
}
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 6a19cf679be..172f2b9069e 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -2024,17 +2024,25 @@ bool autokeyframe_cfra_can_key(Scene *scene, ID *id)
/* only filter if auto-key mode requires this */
if (IS_AUTOKEY_ON(scene) == 0)
return false;
-
- if (IS_AUTOKEY_MODE(scene, NORMAL)) {
- /* can insert anytime we like... */
- return true;
- }
- else { /* REPLACE */
- /* for whole block - only key if there's a keyframe on that frame already
- * this is a valid assumption when we're blocking + tweaking
+
+ if (IS_AUTOKEY_MODE(scene, EDITKEYS)) {
+ /* Replace Mode:
+ * For whole block, only key if there's a keyframe on that frame already
+ * This is a valid assumption when we're blocking + tweaking
*/
return id_frame_has_keyframe(id, cfra, ANIMFILTER_KEYS_LOCAL);
}
+ else {
+ /* Normal Mode (or treat as being normal mode):
+ *
+ * Just in case the flags are't set properly (i.e. only on/off is set, without a mode)
+ * let's set the "normal" flag too, so that it will all be sane everywhere...
+ */
+ scene->toolsettings->autokey_mode = AUTOKEY_MODE_NORMAL;
+
+ /* Can insert anytime we like... */
+ return true;
+ }
}
/* ******************************************* */
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index d73536e5ba7..6306926e0b2 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -367,6 +367,8 @@ void transform_armature_mirror_update(Object *obedit)
eboflip->tail[2] = ebo->tail[2];
eboflip->rad_tail = ebo->rad_tail;
eboflip->roll = -ebo->roll;
+ eboflip->curveOutX = -ebo->curveOutX;
+ eboflip->roll2 = -ebo->roll2;
/* Also move connected children, in case children's name aren't mirrored properly */
for (children = arm->edbo->first; children; children = children->next) {
@@ -382,6 +384,8 @@ void transform_armature_mirror_update(Object *obedit)
eboflip->head[2] = ebo->head[2];
eboflip->rad_head = ebo->rad_head;
eboflip->roll = -ebo->roll;
+ eboflip->curveInX = -ebo->curveInX;
+ eboflip->roll1 = -ebo->roll1;
/* Also move connected parent, in case parent's name isn't mirrored properly */
if (eboflip->parent && eboflip->flag & BONE_CONNECTED) {
@@ -395,6 +399,11 @@ void transform_armature_mirror_update(Object *obedit)
eboflip->roll = -ebo->roll;
eboflip->xwidth = ebo->xwidth;
eboflip->zwidth = ebo->zwidth;
+
+ eboflip->curveInX = -ebo->curveInX;
+ eboflip->curveOutX = -ebo->curveOutX;
+ eboflip->roll1 = -ebo->roll1;
+ eboflip->roll2 = -ebo->roll2;
}
}
}
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index 9e49d7e7e90..d4d3e1af1fd 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -2327,6 +2327,12 @@ static void ui_block_colorpicker(uiBlock *block, float rgba[4], PointerRNA *ptr,
RNA_property_float_range(ptr, prop, &hardmin, &hardmax);
RNA_property_float_get_array(ptr, prop, rgba);
+ /* when the softmax isn't defined in the RNA,
+ * using very large numbers causes sRGB/linear round trip to fail. */
+ if (softmax == FLT_MAX) {
+ softmax = 1.0f;
+ }
+
switch (U.color_picker_type) {
case USER_CP_SQUARE_SV:
ui_colorpicker_square(block, ptr, prop, UI_GRAD_SV, cpicker);
@@ -2418,7 +2424,7 @@ static void ui_block_colorpicker(uiBlock *block, float rgba[4], PointerRNA *ptr,
BLI_snprintf(hexcol, sizeof(hexcol), "%02X%02X%02X", UNPACK3_EX((unsigned int), rgb_gamma_uchar, ));
yco = -3.0f * UI_UNIT_Y;
- bt = uiDefBut(block, UI_BTYPE_TEXT, 0, IFACE_("Hex: "), 0, yco, butwidth, UI_UNIT_Y, hexcol, 0, 8, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
+ bt = uiDefBut(block, UI_BTYPE_TEXT, 0, IFACE_("Hex: "), 0, yco, butwidth, UI_UNIT_Y, hexcol, 0, 7, 0, 0, TIP_("Hex triplet for color (#RRGGBB)"));
UI_but_func_set(bt, ui_colorpicker_hex_rna_cb, bt, hexcol);
bt->custom_data = cpicker;
uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("(Gamma Corrected)"), 0, yco - UI_UNIT_Y, butwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index d4c976fb544..acb8e8e7512 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -94,6 +94,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int triangulate;
int use_object_instantiation;
+ int use_blender_profile;
int sort_by_name;
int export_transformation_type;
int open_sim;
@@ -142,6 +143,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
triangulate = RNA_boolean_get(op->ptr, "triangulate");
use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation");
+ use_blender_profile = RNA_boolean_get(op->ptr, "use_blender_profile");
sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name");
export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection");
open_sim = RNA_boolean_get(op->ptr, "open_sim");
@@ -167,6 +169,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
triangulate,
use_object_instantiation,
+ use_blender_profile,
sort_by_name,
export_transformation_type,
open_sim);
@@ -256,6 +259,8 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(row, imfptr, "triangulate", 0, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "use_object_instantiation", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "use_blender_profile", 0, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
@@ -349,7 +354,10 @@ void WM_OT_collada_export(wmOperatorType *ot)
"Export Polygons (Quads & NGons) as Triangles");
RNA_def_boolean(ot->srna, "use_object_instantiation", 1, "Use Object Instances",
- "Instantiate multiple Objects from same Data");
+ "Instantiate multiple Objects from same Data");
+
+ RNA_def_boolean(ot->srna, "use_blender_profile", 1, "Use Blender Profile",
+ "Export additional Blender specific information (for material, shaders, bones, etc.)");
RNA_def_boolean(ot->srna, "sort_by_name", 0, "Sort by Object name",
"Sort exported data by Object name");
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 0280f662a26..8783367ef7e 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -55,6 +55,7 @@ set(SRC
editmesh_rip_edge.c
editmesh_select.c
editmesh_tools.c
+ editmesh_undo.c
editmesh_utils.c
mesh_data.c
mesh_ops.c
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
new file mode 100644
index 00000000000..b9d3fd6c8be
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -0,0 +1,726 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/mesh/editmesh_undo.c
+ * \ingroup edmesh
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_key_types.h"
+
+#include "BLI_listbase.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_context.h"
+#include "BKE_key.h"
+#include "BKE_mesh.h"
+#include "BKE_editmesh.h"
+
+#include "ED_mesh.h"
+#include "ED_util.h"
+
+#define USE_ARRAY_STORE
+
+#ifdef USE_ARRAY_STORE
+// # define DEBUG_PRINT
+// # define DEBUG_TIME
+# ifdef DEBUG_TIME
+# include "PIL_time_utildefines.h"
+# endif
+
+# include "BLI_array_store.h"
+# include "BLI_math_base.h"
+ /* check on best size later... */
+# define ARRAY_CHUNK_SIZE 256
+
+# define USE_ARRAY_STORE_THREAD
+#endif
+
+#ifdef USE_ARRAY_STORE_THREAD
+# include "BLI_task.h"
+#endif
+
+
+#ifdef USE_ARRAY_STORE
+
+/* Single linked list of layers stored per type */
+typedef struct BArrayCustomData {
+ struct BArrayCustomData *next;
+ CustomDataType type;
+ int states_len; /* number of layers for each type */
+ BArrayState *states[0];
+} BArrayCustomData;
+
+#endif
+
+typedef struct UndoMesh {
+ Mesh me;
+ int selectmode;
+
+ /** \note
+ * this isn't a prefect solution, if you edit keys and change shapes this works well (fixing [#32442]),
+ * but editing shape keys, going into object mode, removing or changing their order,
+ * then go back into editmode and undo will give issues - where the old index will be out of sync
+ * with the new object index.
+ *
+ * There are a few ways this could be made to work but for now its a known limitation with mixing
+ * object and editmode operations - Campbell */
+ int shapenr;
+
+#ifdef USE_ARRAY_STORE
+ /* NULL arrays are considered empty */
+ struct {
+ /* most data is stored as 'custom' data */
+ BArrayCustomData *vdata, *edata, *ldata, *pdata;
+ BArrayState **keyblocks;
+ BArrayState *mselect;
+ } store;
+#endif /* USE_ARRAY_STORE */
+} UndoMesh;
+
+
+#ifdef USE_ARRAY_STORE
+
+/** \name Array Store
+ * \{ */
+
+static struct {
+ BArrayStore **bs_all;
+ int bs_all_len;
+ int users;
+
+ /* We could have the undo API pass in the previous state, for now store a local list */
+ ListBase local_links;
+
+#ifdef USE_ARRAY_STORE_THREAD
+ TaskPool *task_pool;
+#endif
+
+} um_arraystore = {NULL};
+
+static BArrayStore *array_store_at_size_ensure(const int stride)
+{
+ if (um_arraystore.bs_all_len < stride) {
+ um_arraystore.bs_all_len = stride;
+ um_arraystore.bs_all = MEM_recallocN(um_arraystore.bs_all, sizeof(*um_arraystore.bs_all) * stride);
+ }
+ BArrayStore **bs_p = &um_arraystore.bs_all[stride - 1];
+
+ if ((*bs_p) == NULL) {
+#if 0
+ unsigned int chunk_count = ARRAY_CHUNK_SIZE;
+#else
+ /* calculate best chunk-count to fit a power of two */
+ unsigned int chunk_count = ARRAY_CHUNK_SIZE;
+ {
+ unsigned int size = chunk_count * stride;
+ size = power_of_2_max_u(size);
+ size = MEM_SIZE_OPTIMAL(size);
+ chunk_count = size / stride;
+ }
+#endif
+
+ (*bs_p) = BLI_array_store_create(stride, chunk_count);
+ }
+ return *bs_p;
+}
+
+static BArrayStore *array_store_at_size_get(const int stride)
+{
+ BLI_assert(stride > 0 && stride <= um_arraystore.bs_all_len);
+ return um_arraystore.bs_all[stride - 1];
+}
+
+#ifdef DEBUG_PRINT
+static void um_arraystore_memory_usage(size_t *r_size_expanded, size_t *r_size_compacted)
+{
+ size_t size_compacted = 0;
+ size_t size_expanded = 0;
+ for (int i = 0; i < um_arraystore.bs_all_len; i++) {
+ BArrayStore *bs = um_arraystore.bs_all[i];
+ if (bs) {
+ size_compacted += BLI_array_store_calc_size_compacted_get(bs);
+ size_expanded += BLI_array_store_calc_size_expanded_get(bs);
+ }
+ }
+
+ *r_size_expanded = size_expanded;
+ *r_size_compacted = size_compacted;
+}
+#endif
+
+static void um_arraystore_cd_compact(
+ struct CustomData *cdata, const size_t data_len,
+ bool create,
+ const BArrayCustomData *bcd_reference,
+ BArrayCustomData **r_bcd_first)
+{
+ if (data_len == 0) {
+ if (create) {
+ *r_bcd_first = NULL;
+ }
+ }
+
+ const BArrayCustomData *bcd_reference_current = bcd_reference;
+ BArrayCustomData *bcd = NULL, *bcd_first = NULL, *bcd_prev = NULL;
+ for (int layer_start = 0, layer_end; layer_start < cdata->totlayer; layer_start = layer_end) {
+ const CustomDataType type = cdata->layers[layer_start].type;
+
+ layer_end = layer_start + 1;
+ while ((layer_end < cdata->totlayer) &&
+ (type == cdata->layers[layer_end].type))
+ {
+ layer_end++;
+ }
+
+ const int stride = CustomData_sizeof(type);
+ BArrayStore *bs = create ? array_store_at_size_ensure(stride) : NULL;
+ const int layer_len = layer_end - layer_start;
+
+ if (create) {
+ if (bcd_reference_current && (bcd_reference_current->type == type)) {
+ /* common case, the reference is aligned */
+ }
+ else {
+ bcd_reference_current = NULL;
+
+ /* do a full lookup when un-alligned */
+ if (bcd_reference) {
+ const BArrayCustomData *bcd_iter = bcd_reference;
+ while (bcd_iter) {
+ if (bcd_iter->type == type) {
+ bcd_reference_current = bcd_iter;
+ break;
+ }
+ bcd_iter = bcd_iter->next;
+ }
+ }
+ }
+ }
+
+ if (create) {
+ bcd = MEM_callocN(sizeof(BArrayCustomData) + (layer_len * sizeof(BArrayState *)), __func__);
+ bcd->next = NULL;
+ bcd->type = type;
+ bcd->states_len = layer_end - layer_start;
+
+ if (bcd_prev) {
+ bcd_prev->next = bcd;
+ bcd_prev = bcd;
+ }
+ else {
+ bcd_first = bcd;
+ bcd_prev = bcd;
+ }
+ }
+
+ CustomDataLayer *layer = &cdata->layers[layer_start];
+ for (int i = 0; i < layer_len; i++, layer++) {
+ if (create) {
+ if (layer->data) {
+ BArrayState *state_reference =
+ (bcd_reference_current && i < bcd_reference_current->states_len) ?
+ bcd_reference_current->states[i] : NULL;
+ bcd->states[i] = BLI_array_store_state_add(
+ bs, layer->data, (size_t)data_len * stride, state_reference);
+ }
+ else {
+ bcd->states[i] = NULL;
+ }
+ }
+
+ if (layer->data) {
+ MEM_freeN(layer->data);
+ layer->data = NULL;
+ }
+ }
+
+ if (create) {
+ if (bcd_reference_current) {
+ bcd_reference_current = bcd_reference_current->next;
+ }
+ }
+ }
+
+ if (create) {
+ *r_bcd_first = bcd_first;
+ }
+}
+
+/**
+ * \note There is no room for data going out of sync here.
+ * The layers and the states are stored together so this can be kept working.
+ */
+static void um_arraystore_cd_expand(
+ const BArrayCustomData *bcd, struct CustomData *cdata, const size_t data_len)
+{
+ CustomDataLayer *layer = cdata->layers;
+ while (bcd) {
+ const int stride = CustomData_sizeof(bcd->type);
+ for (int i = 0; i < bcd->states_len; i++) {
+ BLI_assert(bcd->type == layer->type);
+ if (bcd->states[i]) {
+ size_t state_len;
+ layer->data = BLI_array_store_state_data_get_alloc(bcd->states[i], &state_len);
+ BLI_assert(stride * data_len == state_len);
+ UNUSED_VARS_NDEBUG(stride, data_len);
+ }
+ else {
+ layer->data = NULL;
+ }
+ layer++;
+ }
+ bcd = bcd->next;
+ }
+}
+
+static void um_arraystore_cd_free(BArrayCustomData *bcd)
+{
+ while (bcd) {
+ BArrayCustomData *bcd_next = bcd->next;
+ const int stride = CustomData_sizeof(bcd->type);
+ BArrayStore *bs = array_store_at_size_get(stride);
+ for (int i = 0; i < bcd->states_len; i++) {
+ if (bcd->states[i]) {
+ BLI_array_store_state_remove(bs, bcd->states[i]);
+ }
+ }
+ MEM_freeN(bcd);
+ bcd = bcd_next;
+ }
+}
+
+/**
+ * \param create: When false, only free the arrays.
+ * This is done since when reading from an undo state, they must be temporarily expanded.
+ * then discarded afterwards, having this argument avoids having 2x code paths.
+ */
+static void um_arraystore_compact_ex(
+ UndoMesh *um, const UndoMesh *um_ref,
+ bool create)
+{
+ Mesh *me = &um->me;
+
+ um_arraystore_cd_compact(&me->vdata, me->totvert, create, um_ref ? um_ref->store.vdata : NULL, &um->store.vdata);
+ um_arraystore_cd_compact(&me->edata, me->totedge, create, um_ref ? um_ref->store.edata : NULL, &um->store.edata);
+ um_arraystore_cd_compact(&me->ldata, me->totloop, create, um_ref ? um_ref->store.ldata : NULL, &um->store.ldata);
+ um_arraystore_cd_compact(&me->pdata, me->totpoly, create, um_ref ? um_ref->store.pdata : NULL, &um->store.pdata);
+
+ if (me->key && me->key->totkey) {
+ const size_t stride = me->key->elemsize;
+ BArrayStore *bs = create ? array_store_at_size_ensure(stride) : NULL;
+ if (create) {
+ um->store.keyblocks = MEM_mallocN(me->key->totkey * sizeof(*um->store.keyblocks), __func__);
+ }
+ KeyBlock *keyblock = me->key->block.first;
+ for (int i = 0; i < me->key->totkey; i++, keyblock = keyblock->next) {
+ if (create) {
+ BArrayState *state_reference =
+ (um_ref && um_ref->me.key && (i < um_ref->me.key->totkey)) ?
+ um_ref->store.keyblocks[i] : NULL;
+ um->store.keyblocks[i] = BLI_array_store_state_add(
+ bs, keyblock->data, (size_t)keyblock->totelem * stride,
+ state_reference);
+ }
+
+ if (keyblock->data) {
+ MEM_freeN(keyblock->data);
+ keyblock->data = NULL;
+ }
+ }
+ }
+
+ if (me->mselect && me->totselect) {
+ BLI_assert(create == (um->store.mselect == NULL));
+ if (create) {
+ BArrayState *state_reference = um_ref ? um_ref->store.mselect : NULL;
+ const size_t stride = sizeof(*me->mselect);
+ BArrayStore *bs = array_store_at_size_ensure(stride);
+ um->store.mselect = BLI_array_store_state_add(
+ bs, me->mselect, (size_t)me->totselect * stride, state_reference);
+ }
+
+ /* keep me->totselect for validation */
+ MEM_freeN(me->mselect);
+ me->mselect = NULL;
+ }
+
+ if (create) {
+ um_arraystore.users += 1;
+ }
+
+ BKE_mesh_update_customdata_pointers(me, false);
+}
+
+/**
+ * Move data from allocated arrays to de-duplicated states and clear arrays.
+ */
+static void um_arraystore_compact(UndoMesh *um, const UndoMesh *um_ref)
+{
+ um_arraystore_compact_ex(um, um_ref, true);
+}
+
+static void um_arraystore_compact_with_info(UndoMesh *um, const UndoMesh *um_ref)
+{
+#ifdef DEBUG_PRINT
+ size_t size_expanded_prev, size_compacted_prev;
+ um_arraystore_memory_usage(&size_expanded_prev, &size_compacted_prev);
+#endif
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(mesh_undo_compact);
+#endif
+
+ um_arraystore_compact(um, um_ref);
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(mesh_undo_compact);
+#endif
+
+#ifdef DEBUG_PRINT
+ {
+ size_t size_expanded, size_compacted;
+ um_arraystore_memory_usage(&size_expanded, &size_compacted);
+
+ const double percent_total = size_expanded ?
+ (((double)size_compacted / (double)size_expanded) * 100.0) : -1.0;
+
+ size_t size_expanded_step = size_expanded - size_expanded_prev;
+ size_t size_compacted_step = size_compacted - size_compacted_prev;
+ const double percent_step = size_expanded_step ?
+ (((double)size_compacted_step / (double)size_expanded_step) * 100.0) : -1.0;
+
+ printf("overall memory use: %.8f%% of expanded size\n", percent_total);
+ printf("step memory use: %.8f%% of expanded size\n", percent_step);
+ }
+#endif
+}
+
+#ifdef USE_ARRAY_STORE_THREAD
+
+struct UMArrayData {
+ UndoMesh *um;
+ const UndoMesh *um_ref; /* can be NULL */
+};
+static void um_arraystore_compact_cb(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
+{
+ struct UMArrayData *um_data = taskdata;
+ um_arraystore_compact_with_info(um_data->um, um_data->um_ref);
+}
+
+#endif /* USE_ARRAY_STORE_THREAD */
+
+/**
+ * Remove data we only expanded for temporary use.
+ */
+static void um_arraystore_expand_clear(UndoMesh *um)
+{
+ um_arraystore_compact_ex(um, NULL, false);
+}
+
+static void um_arraystore_expand(UndoMesh *um)
+{
+ Mesh *me = &um->me;
+
+ um_arraystore_cd_expand(um->store.vdata, &me->vdata, me->totvert);
+ um_arraystore_cd_expand(um->store.edata, &me->edata, me->totedge);
+ um_arraystore_cd_expand(um->store.ldata, &me->ldata, me->totloop);
+ um_arraystore_cd_expand(um->store.pdata, &me->pdata, me->totpoly);
+
+ if (um->store.keyblocks) {
+ const size_t stride = me->key->elemsize;
+ KeyBlock *keyblock = me->key->block.first;
+ for (int i = 0; i < me->key->totkey; i++, keyblock = keyblock->next) {
+ BArrayState *state = um->store.keyblocks[i];
+ size_t state_len;
+ keyblock->data = BLI_array_store_state_data_get_alloc(state, &state_len);
+ BLI_assert(keyblock->totelem == (state_len / stride));
+ UNUSED_VARS_NDEBUG(stride);
+ }
+ }
+
+ if (um->store.mselect) {
+ const size_t stride = sizeof(*me->mselect);
+ BArrayState *state = um->store.mselect;
+ size_t state_len;
+ me->mselect = BLI_array_store_state_data_get_alloc(state, &state_len);
+ BLI_assert(me->totselect == (state_len / stride));
+ UNUSED_VARS_NDEBUG(stride);
+ }
+
+ /* not essential, but prevents accidental dangling pointer access */
+ BKE_mesh_update_customdata_pointers(me, false);
+}
+
+static void um_arraystore_free(UndoMesh *um)
+{
+ Mesh *me = &um->me;
+
+ um_arraystore_cd_free(um->store.vdata);
+ um_arraystore_cd_free(um->store.edata);
+ um_arraystore_cd_free(um->store.ldata);
+ um_arraystore_cd_free(um->store.pdata);
+
+ if (um->store.keyblocks) {
+ const size_t stride = me->key->elemsize;
+ BArrayStore *bs = array_store_at_size_get(stride);
+ for (int i = 0; i < me->key->totkey; i++) {
+ BArrayState *state = um->store.keyblocks[i];
+ BLI_array_store_state_remove(bs, state);
+ }
+ MEM_freeN(um->store.keyblocks);
+ um->store.keyblocks = NULL;
+ }
+
+ if (um->store.mselect) {
+ const size_t stride = sizeof(*me->mselect);
+ BArrayStore *bs = array_store_at_size_get(stride);
+ BArrayState *state = um->store.mselect;
+ BLI_array_store_state_remove(bs, state);
+ um->store.mselect = NULL;
+ }
+
+ um_arraystore.users -= 1;
+
+ BLI_assert(um_arraystore.users >= 0);
+
+ if (um_arraystore.users == 0) {
+#ifdef DEBUG_PRINT
+ printf("mesh undo store: freeing all data!\n");
+#endif
+ for (int i = 0; i < um_arraystore.bs_all_len; i += 1) {
+ if (um_arraystore.bs_all[i]) {
+ BLI_array_store_destroy(um_arraystore.bs_all[i]);
+ }
+ }
+
+ MEM_freeN(um_arraystore.bs_all);
+ um_arraystore.bs_all = NULL;
+ um_arraystore.bs_all_len = 0;
+
+#ifdef USE_ARRAY_STORE_THREAD
+ BLI_task_pool_free(um_arraystore.task_pool);
+ um_arraystore.task_pool = NULL;
+#endif
+ }
+
+}
+
+/** \} */
+
+#endif /* USE_ARRAY_STORE */
+
+
+/* for callbacks */
+/* undo simply makes copies of a bmesh */
+static void *editbtMesh_to_undoMesh(void *emv, void *obdata)
+{
+
+#ifdef USE_ARRAY_STORE_THREAD
+ /* changes this waits is low, but must have finished */
+ if (um_arraystore.task_pool) {
+ BLI_task_pool_work_and_wait(um_arraystore.task_pool);
+ }
+#endif
+
+ BMEditMesh *em = emv;
+ Mesh *obme = obdata;
+
+ UndoMesh *um = MEM_callocN(sizeof(UndoMesh), "undo Mesh");
+
+ /* make sure shape keys work */
+ um->me.key = obme->key ? BKE_key_copy_nolib(obme->key) : NULL;
+
+ /* BM_mesh_validate(em->bm); */ /* for troubleshooting */
+
+ BM_mesh_bm_to_me(
+ em->bm, &um->me, (&(struct BMeshToMeshParams){
+ .cd_mask_extra = CD_MASK_SHAPE_KEYINDEX,
+ }));
+
+ um->selectmode = em->selectmode;
+ um->shapenr = em->bm->shapenr;
+
+#ifdef USE_ARRAY_STORE
+ {
+ /* We could be more clever here,
+ * the previous undo state may be from a separate mesh. */
+ const UndoMesh *um_ref = um_arraystore.local_links.last ?
+ ((LinkData *)um_arraystore.local_links.last)->data : NULL;
+
+ /* add oursrlves */
+ BLI_addtail(&um_arraystore.local_links, BLI_genericNodeN(um));
+
+#ifdef USE_ARRAY_STORE_THREAD
+ if (um_arraystore.task_pool == NULL) {
+ TaskScheduler *scheduler = BLI_task_scheduler_get();
+ um_arraystore.task_pool = BLI_task_pool_create_background(scheduler, NULL);
+ }
+
+ struct UMArrayData *um_data = MEM_mallocN(sizeof(*um_data), __func__);
+ um_data->um = um;
+ um_data->um_ref = um_ref;
+
+ BLI_task_pool_push(
+ um_arraystore.task_pool,
+ um_arraystore_compact_cb, um_data, true, TASK_PRIORITY_LOW);
+#else
+ um_arraystore_compact_with_info(um, um_ref);
+#endif
+ }
+#endif
+
+ return um;
+}
+
+static void undoMesh_to_editbtMesh(void *um_v, void *em_v, void *obdata)
+{
+ BMEditMesh *em = em_v, *em_tmp;
+ Object *ob = em->ob;
+ UndoMesh *um = um_v;
+ BMesh *bm;
+ Key *key = ((Mesh *) obdata)->key;
+
+#ifdef USE_ARRAY_STORE
+#ifdef USE_ARRAY_STORE_THREAD
+ /* changes this waits is low, but must have finished */
+ BLI_task_pool_work_and_wait(um_arraystore.task_pool);
+#endif
+
+#ifdef DEBUG_TIME
+ TIMEIT_START(mesh_undo_expand);
+#endif
+
+ um_arraystore_expand(um);
+
+#ifdef DEBUG_TIME
+ TIMEIT_END(mesh_undo_expand);
+#endif
+#endif /* USE_ARRAY_STORE */
+
+ const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(&um->me);
+
+ em->bm->shapenr = um->shapenr;
+
+ EDBM_mesh_free(em);
+
+ bm = BM_mesh_create(&allocsize);
+
+ BM_mesh_bm_from_me(
+ bm, &um->me, (&(struct BMeshFromMeshParams){
+ .calc_face_normal = true, .active_shapekey = um->shapenr,
+ }));
+
+ em_tmp = BKE_editmesh_create(bm, true);
+ *em = *em_tmp;
+
+ em->selectmode = um->selectmode;
+ bm->selectmode = um->selectmode;
+ em->ob = ob;
+
+ /* T35170: Restore the active key on the RealMesh. Otherwise 'fake' offset propagation happens
+ * if the active is a basis for any other. */
+ if (key && (key->type == KEY_RELATIVE)) {
+ /* Since we can't add, remove or reorder keyblocks in editmode, it's safe to assume
+ * shapenr from restored bmesh and keyblock indices are in sync. */
+ const int kb_act_idx = ob->shapenr - 1;
+
+ /* If it is, let's patch the current mesh key block to its restored value.
+ * Else, the offsets won't be computed and it won't matter. */
+ if (BKE_keyblock_is_basis(key, kb_act_idx)) {
+ KeyBlock *kb_act = BLI_findlink(&key->block, kb_act_idx);
+
+ if (kb_act->totelem != um->me.totvert) {
+ /* The current mesh has some extra/missing verts compared to the undo, adjust. */
+ MEM_SAFE_FREE(kb_act->data);
+ kb_act->data = MEM_mallocN((size_t)(key->elemsize * bm->totvert), __func__);
+ kb_act->totelem = um->me.totvert;
+ }
+
+ BKE_keyblock_update_from_mesh(&um->me, kb_act);
+ }
+ }
+
+ ob->shapenr = um->shapenr;
+
+ MEM_freeN(em_tmp);
+
+#ifdef USE_ARRAY_STORE
+ um_arraystore_expand_clear(um);
+#endif
+}
+
+static void free_undo(void *um_v)
+{
+ UndoMesh *um = um_v;
+ Mesh *me = &um->me;
+
+#ifdef USE_ARRAY_STORE
+
+#ifdef USE_ARRAY_STORE_THREAD
+ /* changes this waits is low, but must have finished */
+ BLI_task_pool_work_and_wait(um_arraystore.task_pool);
+#endif
+
+ /* we need to expand so any allocations in custom-data are freed with the mesh */
+ um_arraystore_expand(um);
+
+ {
+ LinkData *link = BLI_findptr(&um_arraystore.local_links, um, offsetof(LinkData, data));
+ BLI_remlink(&um_arraystore.local_links, link);
+ MEM_freeN(link);
+ }
+ um_arraystore_free(um);
+#endif
+
+ if (me->key) {
+ BKE_key_free(me->key);
+ MEM_freeN(me->key);
+ }
+
+ BKE_mesh_free(me, false);
+ MEM_freeN(me);
+}
+
+static void *getEditMesh(bContext *C)
+{
+ Object *obedit = CTX_data_edit_object(C);
+ if (obedit && obedit->type == OB_MESH) {
+ Mesh *me = obedit->data;
+ return me->edit_btmesh;
+ }
+ return NULL;
+}
+
+/* and this is all the undo system needs to know */
+void undo_push_mesh(bContext *C, const char *name)
+{
+ /* em->ob gets out of date and crashes on mesh undo,
+ * this is an easy way to ensure its OK
+ * though we could investigate the matter further. */
+ Object *obedit = CTX_data_edit_object(C);
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ em->ob = obedit;
+
+ undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL);
+}
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 82ec93c162f..99be37845ee 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -45,7 +45,6 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_depsgraph.h"
-#include "BKE_key.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
@@ -60,7 +59,6 @@
#include "ED_mesh.h"
#include "ED_screen.h"
-#include "ED_util.h"
#include "ED_view3d.h"
#include "mesh_intern.h" /* own include */
@@ -491,140 +489,6 @@ void EDBM_flag_enable_all(BMEditMesh *em, const char hflag)
BM_mesh_elem_hflag_enable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, hflag, true);
}
-/**************-------------- Undo ------------*****************/
-
-/* for callbacks */
-
-static void *getEditMesh(bContext *C)
-{
- Object *obedit = CTX_data_edit_object(C);
- if (obedit && obedit->type == OB_MESH) {
- Mesh *me = obedit->data;
- return me->edit_btmesh;
- }
- return NULL;
-}
-
-typedef struct UndoMesh {
- Mesh me;
- int selectmode;
-
- /** \note
- * this isn't a prefect solution, if you edit keys and change shapes this works well (fixing [#32442]),
- * but editing shape keys, going into object mode, removing or changing their order,
- * then go back into editmode and undo will give issues - where the old index will be out of sync
- * with the new object index.
- *
- * There are a few ways this could be made to work but for now its a known limitation with mixing
- * object and editmode operations - Campbell */
- int shapenr;
-} UndoMesh;
-
-/* undo simply makes copies of a bmesh */
-static void *editbtMesh_to_undoMesh(void *emv, void *obdata)
-{
- BMEditMesh *em = emv;
- Mesh *obme = obdata;
-
- UndoMesh *um = MEM_callocN(sizeof(UndoMesh), "undo Mesh");
-
- /* make sure shape keys work */
- um->me.key = obme->key ? BKE_key_copy_nolib(obme->key) : NULL;
-
- /* BM_mesh_validate(em->bm); */ /* for troubleshooting */
-
- BM_mesh_bm_to_me(
- em->bm, &um->me, (&(struct BMeshToMeshParams){
- .cd_mask_extra = CD_MASK_SHAPE_KEYINDEX,
- }));
-
- um->selectmode = em->selectmode;
- um->shapenr = em->bm->shapenr;
-
- return um;
-}
-
-static void undoMesh_to_editbtMesh(void *umv, void *em_v, void *obdata)
-{
- BMEditMesh *em = em_v, *em_tmp;
- Object *ob = em->ob;
- UndoMesh *um = umv;
- BMesh *bm;
- Key *key = ((Mesh *) obdata)->key;
-
- const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(&um->me);
-
- em->bm->shapenr = um->shapenr;
-
- EDBM_mesh_free(em);
-
- bm = BM_mesh_create(&allocsize);
-
- BM_mesh_bm_from_me(
- bm, &um->me, (&(struct BMeshFromMeshParams){
- .calc_face_normal = true, .active_shapekey = um->shapenr,
- }));
-
- em_tmp = BKE_editmesh_create(bm, true);
- *em = *em_tmp;
-
- em->selectmode = um->selectmode;
- bm->selectmode = um->selectmode;
- em->ob = ob;
-
- /* T35170: Restore the active key on the RealMesh. Otherwise 'fake' offset propagation happens
- * if the active is a basis for any other. */
- if (key && (key->type == KEY_RELATIVE)) {
- /* Since we can't add, remove or reorder keyblocks in editmode, it's safe to assume
- * shapenr from restored bmesh and keyblock indices are in sync. */
- const int kb_act_idx = ob->shapenr - 1;
-
- /* If it is, let's patch the current mesh key block to its restored value.
- * Else, the offsets won't be computed and it won't matter. */
- if (BKE_keyblock_is_basis(key, kb_act_idx)) {
- KeyBlock *kb_act = BLI_findlink(&key->block, kb_act_idx);
-
- if (kb_act->totelem != um->me.totvert) {
- /* The current mesh has some extra/missing verts compared to the undo, adjust. */
- MEM_SAFE_FREE(kb_act->data);
- kb_act->data = MEM_mallocN((size_t)(key->elemsize * bm->totvert), __func__);
- kb_act->totelem = um->me.totvert;
- }
-
- BKE_keyblock_update_from_mesh(&um->me, kb_act);
- }
- }
-
- ob->shapenr = um->shapenr;
-
- MEM_freeN(em_tmp);
-}
-
-static void free_undo(void *me_v)
-{
- Mesh *me = me_v;
- if (me->key) {
- BKE_key_free(me->key);
- MEM_freeN(me->key);
- }
-
- BKE_mesh_free(me, false);
- MEM_freeN(me);
-}
-
-/* and this is all the undo system needs to know */
-void undo_push_mesh(bContext *C, const char *name)
-{
- /* em->ob gets out of date and crashes on mesh undo,
- * this is an easy way to ensure its OK
- * though we could investigate the matter further. */
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- em->ob = obedit;
-
- undo_editmode_push(C, name, getEditMesh, free_undo, undoMesh_to_editbtMesh, editbtMesh_to_undoMesh, NULL);
-}
-
/**
* Return a new UVVertMap from the editmesh
*/
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index b6c026ebd37..20e159f4f51 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -2863,7 +2863,7 @@ static void initBend(TransInfo *t)
//copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
calculateCenterCursor(t, t->center);
- calculateCenterGlobal(t);
+ calculateCenterGlobal(t, t->center, t->center_global);
t->val = 0.0f;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index f4d93389776..4e8aa0cc20b 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -369,6 +369,11 @@ typedef struct TransCustomData {
unsigned int use_free : 1;
} TransCustomData;
+typedef struct TransCenterData {
+ float local[3], global[3];
+ unsigned int is_set : 1;
+} TransCenterData;
+
typedef struct TransInfo {
int mode; /* current mode */
int flag; /* generic flags for special behaviors */
@@ -396,6 +401,9 @@ typedef struct TransInfo {
float center[3]; /* center of transformation (in local-space) */
float center_global[3]; /* center of transformation (in global-space) */
float center2d[2]; /* center in screen coordinates */
+ /* Lazy initialize center data for when we need other center values.
+ * V3D_AROUND_ACTIVE + 1 (static assert checks this) */
+ TransCenterData center_cache[5];
short idx_max; /* maximum index on the input vector */
float snap[3]; /* Snapping Gears */
float snap_spatial[3]; /* Spatial snapping gears(even when rotating, scaling... etc) */
@@ -741,8 +749,11 @@ void restoreTransObjects(TransInfo *t);
void recalcData(TransInfo *t);
void calculateCenter2D(TransInfo *t);
-void calculateCenterGlobal(TransInfo *t);
+void calculateCenterGlobal(
+ TransInfo *t, const float center_local[3],
+ float r_center_global[3]);
+const TransCenterData *transformCenter_from_type(TransInfo *t, int around);
void calculateCenter(TransInfo *t);
/* API functions for getting center points */
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 28202f21c0e..78cebbf2c6e 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1601,16 +1601,18 @@ void calculateCenter2D(TransInfo *t)
}
}
-void calculateCenterGlobal(TransInfo *t)
+void calculateCenterGlobal(
+ TransInfo *t, const float center_local[3],
+ float r_center_global[3])
{
/* setting constraint center */
/* note, init functions may over-ride t->center */
if (t->flag & (T_EDIT | T_POSE)) {
Object *ob = t->obedit ? t->obedit : t->poseobj;
- mul_v3_m4v3(t->center_global, ob->obmat, t->center);
+ mul_v3_m4v3(r_center_global, ob->obmat, center_local);
}
else {
- copy_v3_v3(t->center_global, t->center);
+ copy_v3_v3(r_center_global, center_local);
}
}
@@ -1785,43 +1787,55 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
return ok;
}
-
-void calculateCenter(TransInfo *t)
+static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[3])
{
- switch (t->around) {
+ switch (around) {
case V3D_AROUND_CENTER_BOUNDS:
- calculateCenterBound(t, t->center);
+ calculateCenterBound(t, r_center);
break;
case V3D_AROUND_CENTER_MEAN:
- calculateCenterMedian(t, t->center);
+ calculateCenterMedian(t, r_center);
break;
case V3D_AROUND_CURSOR:
if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP))
- calculateCenterCursor2D(t, t->center);
+ calculateCenterCursor2D(t, r_center);
else if (t->spacetype == SPACE_IPO)
- calculateCenterCursorGraph2D(t, t->center);
+ calculateCenterCursorGraph2D(t, r_center);
else
- calculateCenterCursor(t, t->center);
+ calculateCenterCursor(t, r_center);
break;
case V3D_AROUND_LOCAL_ORIGINS:
/* Individual element center uses median center for helpline and such */
- calculateCenterMedian(t, t->center);
+ calculateCenterMedian(t, r_center);
break;
case V3D_AROUND_ACTIVE:
{
- if (calculateCenterActive(t, false, t->center)) {
+ if (calculateCenterActive(t, false, r_center)) {
/* pass */
}
else {
/* fallback */
- calculateCenterMedian(t, t->center);
+ calculateCenterMedian(t, r_center);
}
break;
}
}
+}
+
+void calculateCenter(TransInfo *t)
+{
+ calculateCenter_FromAround(t, t->around, t->center);
+ calculateCenterGlobal(t, t->center, t->center_global);
+
+ /* avoid calculating again */
+ {
+ TransCenterData *cd = &t->center_cache[t->around];
+ copy_v3_v3(cd->local, t->center);
+ copy_v3_v3(cd->global, t->center_global);
+ cd->is_set = true;
+ }
calculateCenter2D(t);
- calculateCenterGlobal(t);
/* for panning from cameraview */
if (t->flag & T_OBJECT) {
@@ -1875,6 +1889,23 @@ void calculateCenter(TransInfo *t)
}
}
+BLI_STATIC_ASSERT(ARRAY_SIZE(((TransInfo *)NULL)->center_cache) == (V3D_AROUND_ACTIVE + 1), "test size");
+
+/**
+ * Lazy initialize transform center data, when we need to access center values from other types.
+ */
+const TransCenterData *transformCenter_from_type(TransInfo *t, int around)
+{
+ BLI_assert(around <= V3D_AROUND_ACTIVE);
+ TransCenterData *cd = &t->center_cache[around];
+ if (cd->is_set == false) {
+ calculateCenter_FromAround(t, around, cd->local);
+ calculateCenterGlobal(t, cd->local, cd->global);
+ cd->is_set = true;
+ }
+ return cd;
+}
+
void calculatePropRatio(TransInfo *t)
{
TransData *td = t->data;
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 1bb8b768981..cb981bc4771 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -1512,11 +1512,21 @@ static void applyGridIncrement(TransInfo *t, float *val, int max_index, const fl
/* absolute snapping on grid based on global center */
if ((t->tsnap.snap_spatial_grid) && (t->mode == TFM_TRANSLATION)) {
+ const float *center_global = t->center_global;
+
+ /* use a fallback for cursor selection,
+ * this isn't useful as a global center for absolute grid snapping
+ * since its not based on the position of the selection. */
+ if (t->around == V3D_AROUND_CURSOR) {
+ const TransCenterData *cd = transformCenter_from_type(t, V3D_AROUND_CENTER_MEAN);
+ center_global = cd->global;
+ }
+
for (i = 0; i <= max_index; i++) {
/* do not let unconstrained axis jump to absolute grid increments */
if (!(t->con.mode & CON_APPLY) || t->con.mode & (CON_AXIS0 << i)) {
const float iter_fac = fac[action] * asp[i];
- val[i] = iter_fac * roundf((val[i] + t->center_global[i]) / iter_fac) - t->center_global[i];
+ val[i] = iter_fac * roundf((val[i] + center_global[i]) / iter_fac) - center_global[i];
}
}
}
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index a8656c05224..ee7abe08aba 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -147,6 +147,7 @@ typedef struct GPUVertPointLink {
/* used for GLSL materials */
typedef struct GPUAttrib {
int index;
+ int info_index;
int size;
int type;
} GPUAttrib;
@@ -179,6 +180,10 @@ typedef enum {
GPU_BINDING_INDEX = 1,
} GPUBindingType;
+typedef enum {
+ GPU_ATTR_INFO_SRGB = (1 << 0),
+} GPUAttrInfo;
+
/* called before drawing */
void GPU_vertex_setup(struct DerivedMesh *dm);
void GPU_normal_setup(struct DerivedMesh *dm);
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 4c674b460aa..762329ee077 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -104,6 +104,7 @@ typedef struct GPUVertexAttribs {
struct {
int type;
int glindex;
+ int glinfoindoex;
int gltexco;
int attribid;
char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 6ff4a60610b..bd7a3b628c8 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -822,6 +822,12 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda
for (i = 0; i < numdata; i++) {
glEnableVertexAttribArray(data[i].index);
+ int info = 0;
+ if (data[i].type == GL_UNSIGNED_BYTE) {
+ info |= GPU_ATTR_INFO_SRGB;
+ }
+ glUniform1i(data[i].info_index, info);
+
glVertexAttribPointer(data[i].index, data[i].size, data[i].type,
GL_TRUE, elementsize, BUFFER_OFFSET(offset));
offset += data[i].size * GPU_typesize(data[i].type);
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index be5a0ab4173..9f41253b176 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -741,6 +741,7 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
BLI_dynstr_appendf(ds, "%s %s att%d;\n",
GLEW_VERSION_3_0 ? "in" : "attribute",
GPU_DATATYPE_STR[input->type], input->attribid);
+ BLI_dynstr_appendf(ds, "uniform int att%d_info;\n", input->attribid);
BLI_dynstr_appendf(ds, "%s %s var%d;\n",
GLEW_VERSION_3_0 ? "out" : "varying",
GPU_DATATYPE_STR[input->type], input->attribid);
@@ -793,7 +794,8 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
}
#endif
- BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
+ BLI_dynstr_appendf(ds, "\tset_var_from_attr(att%d, att%d_info, var%d);\n",
+ input->attribid, input->attribid, input->attribid);
#ifdef WITH_OPENSUBDIV
if (is_mtface) {
BLI_dynstr_appendf(ds, "#endif\n");
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index c15e49a8ed1..a6d120b8943 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -575,7 +575,7 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
glFramebufferTexture2DEXT(
GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + ofs->color->fb_attachment,
GL_TEXTURE_2D_MULTISAMPLE, ofs->color->bindcode, 0);
- status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER_EXT);
+ status = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
goto finally;
}
@@ -583,11 +583,11 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
/* write into new single-sample buffer */
glGenFramebuffersEXT(1, &fbo_blit);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, fbo_blit);
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fbo_blit);
glFramebufferTexture2DEXT(
- GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0,
+ GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, tex_blit, 0);
- status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER_EXT);
+ status = glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
goto finally;
}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 2bded95a1b5..b2e479043d2 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -207,6 +207,9 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
BLI_snprintf(name, sizeof(name), "att%d", attribs->layer[a].attribid);
attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name);
+ BLI_snprintf(name, sizeof(name), "att%d_info", attribs->layer[a].attribid);
+ attribs->layer[a].glinfoindoex = GPU_shader_get_uniform(shader, name);
+
if (attribs->layer[a].glindex >= 0) {
attribs->layer[b] = attribs->layer[a];
b++;
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
index 2f501dfab05..ad4182340d6 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
@@ -91,7 +91,7 @@ void main()
discard;
}
else if (stipple_id == STIPPLE_CHECKER_8PX) {
- int result = int(mod(int(gl_FragCoord.x)/8 + int(gl_FragCoord.y) / 8, 2));
+ int result = int(mod(int(gl_FragCoord.x) / 8 + int(gl_FragCoord.y) / 8, 2));
if (result != 0)
discard;
}
@@ -165,7 +165,7 @@ void main()
/* diffuse light */
vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
float diffuse_bsdf = max(dot(N, light_direction), 0.0);
- L_diffuse += light_diffuse*diffuse_bsdf;
+ L_diffuse += light_diffuse * diffuse_bsdf;
#ifndef NO_SPECULAR
/* specular light */
@@ -173,7 +173,7 @@ void main()
vec3 H = gl_LightSource[i].halfVector.xyz;
float specular_bsdf = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);
- L_specular += light_specular*specular_bsdf;
+ L_specular += light_specular * specular_bsdf;
#endif
}
#else
@@ -181,7 +181,7 @@ void main()
#ifndef NO_SPECULAR
/* view vector computation, depends on orthographics or perspective */
- vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position): vec3(0.0, 0.0, -1.0);
+ vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position) : vec3(0.0, 0.0, -1.0);
#endif
for (int i = 0; i < NUM_SCENE_LIGHTS; i++) {
@@ -212,14 +212,14 @@ void main()
float distance = length(d);
intensity /= gl_LightSource[i].constantAttenuation +
- gl_LightSource[i].linearAttenuation * distance +
- gl_LightSource[i].quadraticAttenuation * distance * distance;
+ gl_LightSource[i].linearAttenuation * distance +
+ gl_LightSource[i].quadraticAttenuation * distance * distance;
}
/* diffuse light */
vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
float diffuse_bsdf = max(dot(N, light_direction), 0.0);
- L_diffuse += light_diffuse*diffuse_bsdf*intensity;
+ L_diffuse += light_diffuse * diffuse_bsdf * intensity;
#ifndef NO_SPECULAR
/* specular light */
@@ -227,7 +227,7 @@ void main()
vec3 H = normalize(light_direction - V);
float specular_bsdf = pow(max(dot(N, H), 0.0), gl_FrontMaterial.shininess);
- L_specular += light_specular*specular_bsdf*intensity;
+ L_specular += light_specular * specular_bsdf * intensity;
#endif
}
#endif
@@ -257,7 +257,7 @@ void main()
vec3 L = gl_FrontLightModelProduct.sceneColor.rgb + L_diffuse;
#ifndef NO_SPECULAR
- L += L_specular*gl_FrontMaterial.specular.rgb;
+ L += L_specular * gl_FrontMaterial.specular.rgb;
#endif
/* write out fragment color */
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl b/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
index 674dd534352..a88681a5fd3 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_geom.glsl
@@ -1,6 +1,6 @@
/*
-* Used the implementation of wide lines of Timo Suoranta (http://neure.dy.fi/wideline.html)
-*/
+ * Used the implementation of wide lines of Timo Suoranta (http://neure.dy.fi/wideline.html)
+ */
#define PASSTHROUGH 0
@@ -24,72 +24,72 @@ uniform int stipple_factor;
void main(void)
{
- vec2 window_size = viewport.zw;
- vec4 start = gl_in[0].gl_Position;
- vec4 end = gl_in[1].gl_Position;
+ vec2 window_size = viewport.zw;
+ vec4 start = gl_in[0].gl_Position;
+ vec4 end = gl_in[1].gl_Position;
#if PASSTHROUGH
- gl_Position = start; EmitVertex();
- gl_Position = end; EmitVertex();
- EndPrimitive();
- return;
+ gl_Position = start; EmitVertex();
+ gl_Position = end; EmitVertex();
+ EndPrimitive();
+ return;
#endif
-/* t = 0 t = ~(len(end - start) + 2*line_width)
- * A-------------------------------------B
- * | | | |
- * | side | |
- * | | | |
- * |--axis--*start--------------*end-----|
- * | | | |
- * | | | |
- * | | | |
- * D-------------------------------------C
- */
-
- /* Clip the line before homogenization.
- * Compute line start and end distances to nearplane in clipspace
- * Distances are t0 = dot(start, plane) and t1 = dot(end, plane)
- */
- float t0 = start.z + start.w;
- float t1 = end.z + end.w;
- if (t0 < 0.0) {
- if (t1 < 0.0) {
- return;
- }
- start = mix(start, end, (0 - t0) / (t1 - t0));
- }
- if (t1 < 0.0) {
- end = mix(start, end, (0 - t0) / (t1 - t0));
- }
-
- /* Compute line axis and side vector in screen space */
- vec2 startInNDC = start.xy / start.w; /* clip to NDC: homogenize and drop z */
- vec2 endInNDC = end.xy / end.w;
- vec2 lineInNDC = endInNDC - startInNDC;
- vec2 lineInScreen = lineInNDC * window_size; /* ndc to screen (direction vector) */
-
- vec2 axisInScreen = normalize(lineInScreen);
- vec2 sideInScreen = vec2(-axisInScreen.y, axisInScreen.x); /* rotate */
- vec2 axisInNDC = axisInScreen / window_size; /* screen to NDC */
- vec2 sideInNDC = sideInScreen / window_size;
- vec4 axis = vec4(axisInNDC, 0.0, 0.0) * line_width; /* NDC to clip (delta vector) */
- vec4 side = vec4(sideInNDC, 0.0, 0.0) * line_width;
-
- vec4 A = (start + (side - axis) * start.w);
- vec4 B = (end + (side + axis) * end.w);
- vec4 C = (end - (side - axis) * end.w);
- vec4 D = (start - (side + axis) * start.w);
-
- /* There is no relation between lines yet */
- /* TODO Pass here t0 to make continuous pattern. */
- t0 = 0;
- t1 = (length(lineInScreen) + 2*line_width)/ (2*line_width * stipple_factor);
-
- gl_Position = A; t = t0; varying_vertex_color = varying_vertex_color_line[0]; EmitVertex();
- gl_Position = D; t = t0; varying_vertex_color = varying_vertex_color_line[0]; EmitVertex();
- gl_Position = B; t = t1; varying_vertex_color = varying_vertex_color_line[1]; EmitVertex();
- gl_Position = C; t = t1; varying_vertex_color = varying_vertex_color_line[1]; EmitVertex();
- EndPrimitive();
+ /* t = 0 t = ~(len(end - start) + 2*line_width)
+ * A-------------------------------------B
+ * | | | |
+ * | side | |
+ * | | | |
+ * |--axis--*start--------------*end-----|
+ * | | | |
+ * | | | |
+ * | | | |
+ * D-------------------------------------C
+ */
+
+ /* Clip the line before homogenization.
+ * Compute line start and end distances to nearplane in clipspace
+ * Distances are t0 = dot(start, plane) and t1 = dot(end, plane)
+ */
+ float t0 = start.z + start.w;
+ float t1 = end.z + end.w;
+ if (t0 < 0.0) {
+ if (t1 < 0.0) {
+ return;
+ }
+ start = mix(start, end, (0 - t0) / (t1 - t0));
+ }
+ if (t1 < 0.0) {
+ end = mix(start, end, (0 - t0) / (t1 - t0));
+ }
+
+ /* Compute line axis and side vector in screen space */
+ vec2 startInNDC = start.xy / start.w; /* clip to NDC: homogenize and drop z */
+ vec2 endInNDC = end.xy / end.w;
+ vec2 lineInNDC = endInNDC - startInNDC;
+ vec2 lineInScreen = lineInNDC * window_size; /* ndc to screen (direction vector) */
+
+ vec2 axisInScreen = normalize(lineInScreen);
+ vec2 sideInScreen = vec2(-axisInScreen.y, axisInScreen.x); /* rotate */
+ vec2 axisInNDC = axisInScreen / window_size; /* screen to NDC */
+ vec2 sideInNDC = sideInScreen / window_size;
+ vec4 axis = vec4(axisInNDC, 0.0, 0.0) * line_width; /* NDC to clip (delta vector) */
+ vec4 side = vec4(sideInNDC, 0.0, 0.0) * line_width;
+
+ vec4 A = (start + (side - axis) * start.w);
+ vec4 B = (end + (side + axis) * end.w);
+ vec4 C = (end - (side - axis) * end.w);
+ vec4 D = (start - (side + axis) * start.w);
+
+ /* There is no relation between lines yet */
+ /* TODO Pass here t0 to make continuous pattern. */
+ t0 = 0;
+ t1 = (length(lineInScreen) + 2 * line_width) / (2 * line_width * stipple_factor);
+
+ gl_Position = A; t = t0; varying_vertex_color = varying_vertex_color_line[0]; EmitVertex();
+ gl_Position = D; t = t0; varying_vertex_color = varying_vertex_color_line[0]; EmitVertex();
+ gl_Position = B; t = t1; varying_vertex_color = varying_vertex_color_line[1]; EmitVertex();
+ gl_Position = C; t = t1; varying_vertex_color = varying_vertex_color_line[1]; EmitVertex();
+ EndPrimitive();
}
#else
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
index e9dab04de5d..338ef6d51a7 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
@@ -115,9 +115,9 @@ void second_pass()
color += texture2D(colorbuffer, uvcoordsvar.xy + invrendertargetdim) * 0.234375;
color += texture2D(colorbuffer, uvcoordsvar.xy + 2.5 * invrendertargetdim) * 0.09375;
color += texture2D(colorbuffer, uvcoordsvar.xy + 4.5 * invrendertargetdim) * 0.015625;
- color += texture2D(colorbuffer, uvcoordsvar.xy -invrendertargetdim) * 0.234375;
- color += texture2D(colorbuffer, uvcoordsvar.xy -2.5 * invrendertargetdim) * 0.09375;
- color += texture2D(colorbuffer, uvcoordsvar.xy -4.5 * invrendertargetdim) * 0.015625;
+ color += texture2D(colorbuffer, uvcoordsvar.xy - invrendertargetdim) * 0.234375;
+ color += texture2D(colorbuffer, uvcoordsvar.xy - 2.5 * invrendertargetdim) * 0.09375;
+ color += texture2D(colorbuffer, uvcoordsvar.xy - 4.5 * invrendertargetdim) * 0.015625;
gl_FragColor = color;
}
@@ -128,7 +128,7 @@ void third_pass()
{
vec4 color = texture2D(colorbuffer, uvcoordsvar.xy);
vec4 color_blurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
- float coc = 2.0 * max(color_blurred.a, color.a); - color.a;
+ float coc = 2.0 * max(color_blurred.a, color.a); -color.a;
gl_FragColor = vec4(color.rgb, coc);
}
@@ -146,7 +146,7 @@ void fourth_pass()
vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
{
- float weight = 1.0/ 17.0;
+ float weight = 1.0 / 17.0;
vec4 result = weight * color;
weight *= 4.0;
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
index 7657fbb71ab..182113367d3 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
@@ -103,7 +103,7 @@ void accumulate_pass(void) {
r = 1.0;
else
r = cos(M_PI / dof_params.w) /
- (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI))));
+ (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI))));
if (dot(particlecoord, particlecoord) > r * r)
discard;
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
index a2ef990c4e8..63b57d5775c 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
@@ -38,8 +38,12 @@ void vert_dof_first_pass()
void vert_dof_fourth_pass()
{
vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
- uvcoordsvar = gl_MultiTexCoord0.xxyy + halfpixel * vec4(invrendertargetdim.x,
- invrendertargetdim.x, invrendertargetdim.y, invrendertargetdim.y);
+ uvcoordsvar = gl_MultiTexCoord0.xxyy +
+ halfpixel *
+ vec4(invrendertargetdim.x,
+ invrendertargetdim.x,
+ invrendertargetdim.y,
+ invrendertargetdim.y);
gl_Position = gl_Vertex;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
index c2cd927898e..054a2f795ee 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
@@ -77,7 +77,7 @@ float calculate_ssao_factor(float depth)
/* use minor bias here to avoid self shadowing */
if (f > 0.05 * len + 0.0001)
- factor += f * 1.0/(len * (1.0 + len * len * ssao_params.z));
+ factor += f * 1.0 / (len * (1.0 + len * len * ssao_params.z));
}
}
diff --git a/source/blender/gpu/shaders/gpu_shader_geometry.glsl b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
index 16fba0dd055..1663915549c 100644
--- a/source/blender/gpu/shaders/gpu_shader_geometry.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
@@ -49,7 +49,7 @@ void emit_flat(int index, vec3 normal)
varposition = outpt.v.position.xyz;
/* TODO(sergey): Only uniform subdivisions atm. */
- vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
vec2 st = quadst[index];
INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
@@ -70,7 +70,7 @@ void emit_smooth(int index)
varposition = outpt.v.position.xyz;
/* TODO(sergey): Only uniform subdivisions atm. */
- vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
vec2 st = quadst[index];
INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index a63e7b8dbf0..9914c4bb362 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -3,7 +3,7 @@
float convert_rgba_to_float(vec4 color)
{
#ifdef USE_NEW_SHADING
- return color.r*0.2126 + color.g*0.7152 + color.b*0.0722;
+ return color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722;
#else
return (color.r + color.g + color.b) / 3.0;
#endif
@@ -39,11 +39,11 @@ void rgb_to_hsv(vec4 rgb, out vec4 outcol)
cmax = max(rgb[0], max(rgb[1], rgb[2]));
cmin = min(rgb[0], min(rgb[1], rgb[2]));
- cdelta = cmax-cmin;
+ cdelta = cmax - cmin;
v = cmax;
- if (cmax!=0.0)
- s = cdelta/cmax;
+ if (cmax != 0.0)
+ s = cdelta / cmax;
else {
s = 0.0;
h = 0.0;
@@ -53,15 +53,15 @@ void rgb_to_hsv(vec4 rgb, out vec4 outcol)
h = 0.0;
}
else {
- c = (vec3(cmax, cmax, cmax) - rgb.xyz)/cdelta;
+ c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta;
- if (rgb.x==cmax) h = c[2] - c[1];
- else if (rgb.y==cmax) h = 2.0 + c[0] - c[2];
+ if (rgb.x == cmax) h = c[2] - c[1];
+ else if (rgb.y == cmax) h = 2.0 + c[0] - c[2];
else h = 4.0 + c[1] - c[0];
h /= 6.0;
- if (h<0.0)
+ if (h < 0.0)
h += 1.0;
}
@@ -77,21 +77,21 @@ void hsv_to_rgb(vec4 hsv, out vec4 outcol)
s = hsv[1];
v = hsv[2];
- if (s==0.0) {
+ if (s == 0.0) {
rgb = vec3(v, v, v);
}
else {
- if (h==1.0)
+ if (h == 1.0)
h = 0.0;
-
+
h *= 6.0;
i = floor(h);
f = h - i;
rgb = vec3(f, f, f);
- p = v*(1.0-s);
- q = v*(1.0-(s*f));
- t = v*(1.0-(s*(1.0-f)));
-
+ p = v * (1.0 - s);
+ q = v * (1.0 - (s * f));
+ t = v * (1.0 - (s * (1.0 - f)));
+
if (i == 0.0) rgb = vec3(v, t, p);
else if (i == 1.0) rgb = vec3(q, v, p);
else if (i == 2.0) rgb = vec3(p, v, t);
@@ -106,17 +106,17 @@ void hsv_to_rgb(vec4 hsv, out vec4 outcol)
float srgb_to_linearrgb(float c)
{
if (c < 0.04045)
- return (c < 0.0) ? 0.0: c * (1.0 / 12.92);
+ return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
else
- return pow((c + 0.055)*(1.0/1.055), 2.4);
+ return pow((c + 0.055) * (1.0 / 1.055), 2.4);
}
float linearrgb_to_srgb(float c)
{
if (c < 0.0031308)
- return (c < 0.0) ? 0.0: c * 12.92;
+ return (c < 0.0) ? 0.0 : c * 12.92;
else
- return 1.055 * pow(c, 1.0/2.4) - 0.055;
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
}
void srgb_to_linearrgb(vec4 col_from, out vec4 col_to)
@@ -168,7 +168,7 @@ void vcol_attribute(vec4 attvcol, out vec4 vcol)
void uv_attribute(vec2 attuv, out vec3 uv)
{
- uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0);
+ uv = vec3(attuv * 2.0 - vec2(1.0, 1.0), 0.0);
}
void geom(
@@ -177,15 +177,15 @@ void geom(
out vec3 normal, out vec4 vcol, out float vcol_alpha, out float frontback)
{
local = co;
- view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(local): vec3(0.0, 0.0, -1.0);
- global = (viewinvmat*vec4(local, 1.0)).xyz;
+ view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(local) : vec3(0.0, 0.0, -1.0);
+ global = (viewinvmat * vec4(local, 1.0)).xyz;
orco = attorco;
uv_attribute(attuv, uv);
- normal = -normalize(nor); /* blender render normal is negated */
+ normal = -normalize(nor); /* blender render normal is negated */
vcol_attribute(attvcol, vcol);
srgb_to_linearrgb(vcol, vcol);
vcol_alpha = attvcol.a;
- frontback = (gl_FrontFacing)? 1.0: 0.0;
+ frontback = (gl_FrontFacing) ? 1.0 : 0.0;
}
void particle_info(
@@ -210,12 +210,48 @@ void vect_normalize(vec3 vin, out vec3 vout)
void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout)
{
- vout = (mat*vec4(vin, 0.0)).xyz;
+ vout = (mat * vec4(vin, 0.0)).xyz;
}
void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout)
{
- vout = (mat*vec4(vin, 1.0)).xyz;
+ vout = (mat * vec4(vin, 1.0)).xyz;
+}
+
+void point_texco_remap_square(vec3 vin, out vec3 vout)
+{
+ vout = vec3(vin - vec3(0.5, 0.5, 0.5)) * 2.0;
+}
+
+void point_map_to_sphere(vec3 vin, out vec3 vout)
+{
+ float len = length(vin);
+ float v, u;
+ if (len > 0.0) {
+ if (vin.x == 0.0 && vin.y == 0.0)
+ u = 0.0;
+ else
+ u = (1.0 - atan(vin.x, vin.y) / M_PI) / 2.0;
+
+ v = 1.0 - acos(vin.z / len) / M_PI;
+ }
+ else
+ v = u = 0.0;
+
+ vout = vec3(u, v, 0.0);
+}
+
+void point_map_to_tube(vec3 vin, out vec3 vout)
+{
+ float u, v;
+ v = (vin.z + 1.0) * 0.5;
+ float len = sqrt(vin.x * vin.x + vin.y * vin[1]);
+ if (len > 0.0)
+ u = (1.0 - (atan(vin.x / len, vin.y / len) / M_PI)) * 0.5;
+ else
+ v = u = 0.0;
+
+ vout = vec3(u, v, 0.0);
}
void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec)
@@ -322,9 +358,9 @@ void math_pow(float val1, float val2, out float outval)
void math_log(float val1, float val2, out float outval)
{
if (val1 > 0.0 && val2 > 0.0)
- outval= log2(val1) / log2(val2);
+ outval = log2(val1) / log2(val2);
else
- outval= 0.0;
+ outval = 0.0;
}
void math_max(float val1, float val2, out float outval)
@@ -339,7 +375,7 @@ void math_min(float val1, float val2, out float outval)
void math_round(float val, out float outval)
{
- outval= floor(val + 0.5);
+ outval = floor(val + 0.5);
}
void math_less_than(float val1, float val2, out float outval)
@@ -377,19 +413,19 @@ void math_abs(float val1, out float outval)
void squeeze(float val, float width, float center, out float outval)
{
- outval = 1.0/(1.0 + pow(2.71828183, -((val-center)*width)));
+ outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width)));
}
void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
{
outvec = v1 + v2;
- outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0;
+ outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) / 3.0;
}
void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
{
outvec = v1 - v2;
- outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0;
+ outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) / 3.0;
}
void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
@@ -400,7 +436,7 @@ void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
}
void vec_math_mix(float strength, vec3 v1, vec3 v2, out vec3 outvec)
{
- outvec = strength*v1 + (1 - strength) * v2;
+ outvec = strength * v1 + (1 - strength) * v2;
}
void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
@@ -447,12 +483,12 @@ void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
{
- outvec.x = texture2D(curvemap, vec2((vec.x + 1.0)*0.5, 0.0)).x;
- outvec.y = texture2D(curvemap, vec2((vec.y + 1.0)*0.5, 0.0)).y;
- outvec.z = texture2D(curvemap, vec2((vec.z + 1.0)*0.5, 0.0)).z;
+ outvec.x = texture2D(curvemap, vec2((vec.x + 1.0) * 0.5, 0.0)).x;
+ outvec.y = texture2D(curvemap, vec2((vec.y + 1.0) * 0.5, 0.0)).y;
+ outvec.z = texture2D(curvemap, vec2((vec.z + 1.0) * 0.5, 0.0)).z;
if (fac != 1.0)
- outvec = (outvec*fac) + (vec*(1.0-fac));
+ outvec = (outvec * fac) + (vec * (1.0 - fac));
}
@@ -463,7 +499,7 @@ void curves_rgb(float fac, vec4 col, sampler2D curvemap, out vec4 outcol)
outcol.b = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.b, 0.0)).a, 0.0)).b;
if (fac != 1.0)
- outcol = (outcol*fac) + (col*(1.0-fac));
+ outcol = (outcol * fac) + (col * (1.0 - fac));
outcol.a = col.a;
}
@@ -516,11 +552,11 @@ void set_rgba_one(out vec4 outval)
void brightness_contrast(vec4 col, float brightness, float contrast, out vec4 outcol)
{
float a = 1.0 + contrast;
- float b = brightness - contrast*0.5;
+ float b = brightness - contrast * 0.5;
- outcol.r = max(a*col.r + b, 0.0);
- outcol.g = max(a*col.g + b, 0.0);
- outcol.b = max(a*col.b + b, 0.0);
+ outcol.r = max(a * col.r + b, 0.0);
+ outcol.g = max(a * col.g + b, 0.0);
+ outcol.b = max(a * col.b + b, 0.0);
outcol.a = col.a;
}
@@ -550,7 +586,7 @@ void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol)
fac = clamp(fac, 0.0, 1.0);
float facm = 1.0 - fac;
- outcol = vec4(1.0) - (vec4(facm) + fac*(vec4(1.0) - col2))*(vec4(1.0) - col1);
+ outcol = vec4(1.0) - (vec4(facm) + fac * (vec4(1.0) - col2)) * (vec4(1.0) - col1);
outcol.a = col1.a;
}
@@ -562,19 +598,19 @@ void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol)
outcol = col1;
if (outcol.r < 0.5)
- outcol.r *= facm + 2.0*fac*col2.r;
+ outcol.r *= facm + 2.0 * fac * col2.r;
else
- outcol.r = 1.0 - (facm + 2.0*fac*(1.0 - col2.r))*(1.0 - outcol.r);
+ outcol.r = 1.0 - (facm + 2.0 * fac * (1.0 - col2.r)) * (1.0 - outcol.r);
if (outcol.g < 0.5)
- outcol.g *= facm + 2.0*fac*col2.g;
+ outcol.g *= facm + 2.0 * fac * col2.g;
else
- outcol.g = 1.0 - (facm + 2.0*fac*(1.0 - col2.g))*(1.0 - outcol.g);
+ outcol.g = 1.0 - (facm + 2.0 * fac * (1.0 - col2.g)) * (1.0 - outcol.g);
if (outcol.b < 0.5)
- outcol.b *= facm + 2.0*fac*col2.b;
+ outcol.b *= facm + 2.0 * fac * col2.b;
else
- outcol.b = 1.0 - (facm + 2.0*fac*(1.0 - col2.b))*(1.0 - outcol.b);
+ outcol.b = 1.0 - (facm + 2.0 * fac * (1.0 - col2.b)) * (1.0 - outcol.b);
}
void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol)
@@ -591,9 +627,9 @@ void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol)
outcol = col1;
- if (col2.r != 0.0) outcol.r = facm*outcol.r + fac*outcol.r/col2.r;
- if (col2.g != 0.0) outcol.g = facm*outcol.g + fac*outcol.g/col2.g;
- if (col2.b != 0.0) outcol.b = facm*outcol.b + fac*outcol.b/col2.b;
+ if (col2.r != 0.0) outcol.r = facm * outcol.r + fac * outcol.r / col2.r;
+ if (col2.g != 0.0) outcol.g = facm * outcol.g + fac * outcol.g / col2.g;
+ if (col2.b != 0.0) outcol.b = facm * outcol.b + fac * outcol.b / col2.b;
}
void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol)
@@ -606,14 +642,14 @@ void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol)
void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol)
{
fac = clamp(fac, 0.0, 1.0);
- outcol.rgb = min(col1.rgb, col2.rgb*fac);
+ outcol.rgb = min(col1.rgb, col2.rgb * fac);
outcol.a = col1.a;
}
void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol)
{
fac = clamp(fac, 0.0, 1.0);
- outcol.rgb = max(col1.rgb, col2.rgb*fac);
+ outcol.rgb = max(col1.rgb, col2.rgb * fac);
outcol.a = col1.a;
}
@@ -623,28 +659,28 @@ void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol)
outcol = col1;
if (outcol.r != 0.0) {
- float tmp = 1.0 - fac*col2.r;
+ float tmp = 1.0 - fac * col2.r;
if (tmp <= 0.0)
outcol.r = 1.0;
- else if ((tmp = outcol.r/tmp) > 1.0)
+ else if ((tmp = outcol.r / tmp) > 1.0)
outcol.r = 1.0;
else
outcol.r = tmp;
}
if (outcol.g != 0.0) {
- float tmp = 1.0 - fac*col2.g;
+ float tmp = 1.0 - fac * col2.g;
if (tmp <= 0.0)
outcol.g = 1.0;
- else if ((tmp = outcol.g/tmp) > 1.0)
+ else if ((tmp = outcol.g / tmp) > 1.0)
outcol.g = 1.0;
else
outcol.g = tmp;
}
if (outcol.b != 0.0) {
- float tmp = 1.0 - fac*col2.b;
+ float tmp = 1.0 - fac * col2.b;
if (tmp <= 0.0)
outcol.b = 1.0;
- else if ((tmp = outcol.b/tmp) > 1.0)
+ else if ((tmp = outcol.b / tmp) > 1.0)
outcol.b = 1.0;
else
outcol.b = tmp;
@@ -658,30 +694,30 @@ void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol)
outcol = col1;
- tmp = facm + fac*col2.r;
+ tmp = facm + fac * col2.r;
if (tmp <= 0.0)
outcol.r = 0.0;
- else if ((tmp = (1.0 - (1.0 - outcol.r)/tmp)) < 0.0)
+ else if ((tmp = (1.0 - (1.0 - outcol.r) / tmp)) < 0.0)
outcol.r = 0.0;
else if (tmp > 1.0)
outcol.r = 1.0;
else
outcol.r = tmp;
- tmp = facm + fac*col2.g;
+ tmp = facm + fac * col2.g;
if (tmp <= 0.0)
outcol.g = 0.0;
- else if ((tmp = (1.0 - (1.0 - outcol.g)/tmp)) < 0.0)
+ else if ((tmp = (1.0 - (1.0 - outcol.g) / tmp)) < 0.0)
outcol.g = 0.0;
else if (tmp > 1.0)
outcol.g = 1.0;
else
outcol.g = tmp;
- tmp = facm + fac*col2.b;
+ tmp = facm + fac * col2.b;
if (tmp <= 0.0)
outcol.b = 0.0;
- else if ((tmp = (1.0 - (1.0 - outcol.b)/tmp)) < 0.0)
+ else if ((tmp = (1.0 - (1.0 - outcol.b) / tmp)) < 0.0)
outcol.b = 0.0;
else if (tmp > 1.0)
outcol.b = 1.0;
@@ -702,7 +738,7 @@ void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol)
if (hsv2.y != 0.0) {
rgb_to_hsv(outcol, hsv);
hsv.x = hsv2.x;
- hsv_to_rgb(hsv, tmp);
+ hsv_to_rgb(hsv, tmp);
outcol = mix(outcol, tmp, fac);
outcol.a = col1.a;
@@ -722,7 +758,7 @@ void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol)
if (hsv.y != 0.0) {
rgb_to_hsv(col2, hsv2);
- hsv.y = facm*hsv.y + fac*hsv2.y;
+ hsv.y = facm * hsv.y + fac * hsv2.y;
hsv_to_rgb(hsv, outcol);
}
}
@@ -736,7 +772,7 @@ void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol)
rgb_to_hsv(col1, hsv);
rgb_to_hsv(col2, hsv2);
- hsv.z = facm*hsv.z + fac*hsv2.z;
+ hsv.z = facm * hsv.z + fac * hsv2.z;
hsv_to_rgb(hsv, outcol);
}
@@ -754,7 +790,7 @@ void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol)
rgb_to_hsv(outcol, hsv);
hsv.x = hsv2.x;
hsv.y = hsv2.y;
- hsv_to_rgb(hsv, tmp);
+ hsv_to_rgb(hsv, tmp);
outcol = mix(outcol, tmp, fac);
outcol.a = col1.a;
@@ -766,16 +802,16 @@ void mix_soft(float fac, vec4 col1, vec4 col2, out vec4 outcol)
fac = clamp(fac, 0.0, 1.0);
float facm = 1.0 - fac;
- vec4 one= vec4(1.0);
- vec4 scr= one - (one - col2)*(one - col1);
- outcol = facm*col1 + fac*((one - col1)*col2*col1 + col1*scr);
+ vec4 one = vec4(1.0);
+ vec4 scr = one - (one - col2) * (one - col1);
+ outcol = facm * col1 + fac * ((one - col1) * col2 * col1 + col1 * scr);
}
void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
{
fac = clamp(fac, 0.0, 1.0);
- outcol = col1 + fac*(2.0*(col2 - vec4(0.5)));
+ outcol = col1 + fac * (2.0 * (col2 - vec4(0.5)));
}
void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha)
@@ -784,12 +820,12 @@ void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha
outalpha = outcol.a;
}
-void rgbtobw(vec4 color, out float outval)
+void rgbtobw(vec4 color, out float outval)
{
#ifdef USE_NEW_SHADING
- outval = color.r*0.2126 + color.g*0.7152 + color.b*0.0722;
+ outval = color.r * 0.2126 + color.g * 0.7152 + color.b * 0.0722;
#else
- outval = color.r*0.35 + color.g*0.45 + color.b*0.2; /* keep these factors in sync with texture.h:RGBTOBW */
+ outval = color.r * 0.35 + color.g * 0.45 + color.b * 0.2; /* keep these factors in sync with texture.h:RGBTOBW */
#endif
}
@@ -816,11 +852,11 @@ void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 ou
rgb_to_hsv(col, hsv);
hsv[0] += (hue - 0.5);
- if (hsv[0]>1.0) hsv[0]-=1.0; else if (hsv[0]<0.0) hsv[0]+= 1.0;
+ if (hsv[0] > 1.0) hsv[0] -= 1.0; else if (hsv[0] < 0.0) hsv[0] += 1.0;
hsv[1] *= sat;
- if (hsv[1]>1.0) hsv[1]= 1.0; else if (hsv[1]<0.0) hsv[1]= 0.0;
+ if (hsv[1] > 1.0) hsv[1] = 1.0; else if (hsv[1] < 0.0) hsv[1] = 0.0;
hsv[2] *= value;
- if (hsv[2]>1.0) hsv[2]= 1.0; else if (hsv[2]<0.0) hsv[2]= 0.0;
+ if (hsv[2] > 1.0) hsv[2] = 1.0; else if (hsv[2] < 0.0) hsv[2] = 0.0;
hsv_to_rgb(hsv, outcol);
@@ -880,19 +916,19 @@ void texture_flip_blend(vec3 vec, out vec3 outvec)
void texture_blend_lin(vec3 vec, out float outval)
{
- outval = (1.0+vec.x)/2.0;
+ outval = (1.0 + vec.x) / 2.0;
}
void texture_blend_quad(vec3 vec, out float outval)
{
- outval = max((1.0+vec.x)/2.0, 0.0);
+ outval = max((1.0 + vec.x) / 2.0, 0.0);
outval *= outval;
}
void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal)
{
- float a = sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z)*20.0;
- float wi = 0.5 + 0.5*sin(a);
+ float a = sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z) * 20.0;
+ float wi = 0.5 + 0.5 * sin(a);
value = wi;
color = vec4(wi, wi, wi, 1.0);
@@ -901,12 +937,12 @@ void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal
void texture_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal)
{
- color = texture2D(ima, (vec.xy + vec2(1.0, 1.0))*0.5);
+ color = texture2D(ima, (vec.xy + vec2(1.0, 1.0)) * 0.5);
value = color.a;
- normal.x = 2.0*(color.r - 0.5);
- normal.y = 2.0*(0.5 - color.g);
- normal.z = 2.0*(color.b - 0.5);
+ normal.x = 2.0 * (color.r - 0.5);
+ normal.y = 2.0 * (0.5 - color.g);
+ normal.z = 2.0 * (color.b - 0.5);
}
/************* MTEX *****************/
@@ -937,17 +973,17 @@ void texco_tangent(vec4 tangent, out vec3 outtangent)
void texco_global(mat4 viewinvmat, vec3 co, out vec3 global)
{
- global = (viewinvmat*vec4(co, 1.0)).xyz;
+ global = (viewinvmat * vec4(co, 1.0)).xyz;
}
void texco_object(mat4 viewinvmat, mat4 obinvmat, vec3 co, out vec3 object)
{
- object = (obinvmat*(viewinvmat*vec4(co, 1.0))).xyz;
+ object = (obinvmat * (viewinvmat * vec4(co, 1.0))).xyz;
}
void texco_refl(vec3 vn, vec3 view, out vec3 ref)
{
- ref = view - 2.0*dot(vn, view)*vn;
+ ref = view - 2.0 * dot(vn, view) * vn;
}
void shade_norm(vec3 normal, out vec3 outnormal)
@@ -966,9 +1002,9 @@ void mtex_rgb_blend(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 i
float facm;
fact *= facg;
- facm = 1.0-fact;
+ facm = 1.0 - fact;
- incol = fact*texcol + facm*outcol;
+ incol = fact * texcol + facm * outcol;
}
void mtex_rgb_mul(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
@@ -976,9 +1012,9 @@ void mtex_rgb_mul(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 inc
float facm;
fact *= facg;
- facm = 1.0-fact;
+ facm = 1.0 - fact;
- incol = (facm + fact*texcol)*outcol;
+ incol = (facm + fact * texcol) * outcol;
}
void mtex_rgb_screen(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
@@ -986,9 +1022,9 @@ void mtex_rgb_screen(vec3 outcol, vec3 texcol, float fact, float facg, out vec3
float facm;
fact *= facg;
- facm = 1.0-fact;
+ facm = 1.0 - fact;
- incol = vec3(1.0) - (vec3(facm) + fact*(vec3(1.0) - texcol))*(vec3(1.0) - outcol);
+ incol = vec3(1.0) - (vec3(facm) + fact * (vec3(1.0) - texcol)) * (vec3(1.0) - outcol);
}
void mtex_rgb_overlay(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
@@ -996,32 +1032,32 @@ void mtex_rgb_overlay(vec3 outcol, vec3 texcol, float fact, float facg, out vec3
float facm;
fact *= facg;
- facm = 1.0-fact;
+ facm = 1.0 - fact;
if (outcol.r < 0.5)
- incol.r = outcol.r*(facm + 2.0*fact*texcol.r);
+ incol.r = outcol.r * (facm + 2.0 * fact * texcol.r);
else
- incol.r = 1.0 - (facm + 2.0*fact*(1.0 - texcol.r))*(1.0 - outcol.r);
+ incol.r = 1.0 - (facm + 2.0 * fact * (1.0 - texcol.r)) * (1.0 - outcol.r);
if (outcol.g < 0.5)
- incol.g = outcol.g*(facm + 2.0*fact*texcol.g);
+ incol.g = outcol.g * (facm + 2.0 * fact * texcol.g);
else
- incol.g = 1.0 - (facm + 2.0*fact*(1.0 - texcol.g))*(1.0 - outcol.g);
+ incol.g = 1.0 - (facm + 2.0 * fact * (1.0 - texcol.g)) * (1.0 - outcol.g);
if (outcol.b < 0.5)
- incol.b = outcol.b*(facm + 2.0*fact*texcol.b);
+ incol.b = outcol.b * (facm + 2.0 * fact * texcol.b);
else
- incol.b = 1.0 - (facm + 2.0*fact*(1.0 - texcol.b))*(1.0 - outcol.b);
+ incol.b = 1.0 - (facm + 2.0 * fact * (1.0 - texcol.b)) * (1.0 - outcol.b);
}
void mtex_rgb_sub(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
{
- incol = -fact*facg*texcol + outcol;
+ incol = -fact * facg * texcol + outcol;
}
void mtex_rgb_add(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
{
- incol = fact*facg*texcol + outcol;
+ incol = fact * facg * texcol + outcol;
}
void mtex_rgb_div(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
@@ -1029,11 +1065,11 @@ void mtex_rgb_div(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 inc
float facm;
fact *= facg;
- facm = 1.0-fact;
+ facm = 1.0 - fact;
- if (texcol.r != 0.0) incol.r = facm*outcol.r + fact*outcol.r/texcol.r;
- if (texcol.g != 0.0) incol.g = facm*outcol.g + fact*outcol.g/texcol.g;
- if (texcol.b != 0.0) incol.b = facm*outcol.b + fact*outcol.b/texcol.b;
+ if (texcol.r != 0.0) incol.r = facm * outcol.r + fact * outcol.r / texcol.r;
+ if (texcol.g != 0.0) incol.g = facm * outcol.g + fact * outcol.g / texcol.g;
+ if (texcol.b != 0.0) incol.b = facm * outcol.b + fact * outcol.b / texcol.b;
}
void mtex_rgb_diff(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
@@ -1041,9 +1077,9 @@ void mtex_rgb_diff(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 in
float facm;
fact *= facg;
- facm = 1.0-fact;
+ facm = 1.0 - fact;
- incol = facm*outcol + fact*abs(texcol - outcol);
+ incol = facm * outcol + fact * abs(texcol - outcol);
}
void mtex_rgb_dark(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
@@ -1051,7 +1087,7 @@ void mtex_rgb_dark(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 in
float facm, col;
fact *= facg;
- facm = 1.0-fact;
+ facm = 1.0 - fact;
incol.r = min(outcol.r, texcol.r) * fact + outcol.r * facm;
incol.g = min(outcol.g, texcol.g) * fact + outcol.g * facm;
@@ -1064,11 +1100,11 @@ void mtex_rgb_light(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 i
fact *= facg;
- col = fact*texcol.r;
+ col = fact * texcol.r;
if (col > outcol.r) incol.r = col; else incol.r = outcol.r;
- col = fact*texcol.g;
+ col = fact * texcol.g;
if (col > outcol.g) incol.g = col; else incol.g = outcol.g;
- col = fact*texcol.b;
+ col = fact * texcol.b;
if (col > outcol.b) incol.b = col; else incol.b = outcol.b;
}
@@ -1076,7 +1112,7 @@ void mtex_rgb_hue(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 inc
{
vec4 col;
- mix_hue(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
+ mix_hue(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
incol.rgb = col.rgb;
}
@@ -1084,7 +1120,7 @@ void mtex_rgb_sat(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 inc
{
vec4 col;
- mix_sat(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
+ mix_sat(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
incol.rgb = col.rgb;
}
@@ -1092,7 +1128,7 @@ void mtex_rgb_val(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 inc
{
vec4 col;
- mix_val(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
+ mix_val(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
incol.rgb = col.rgb;
}
@@ -1100,7 +1136,7 @@ void mtex_rgb_color(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 i
{
vec4 col;
- mix_color(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
+ mix_color(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col);
incol.rgb = col.rgb;
}
@@ -1109,11 +1145,11 @@ void mtex_rgb_soft(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 in
float facm;
fact *= facg;
- facm = 1.0-fact;
+ facm = 1.0 - fact;
vec3 one = vec3(1.0);
- vec3 scr = one - (one - texcol)*(one - outcol);
- incol = facm*outcol + fact*((one - texcol)*outcol*texcol + outcol*scr);
+ vec3 scr = one - (one - texcol) * (one - outcol);
+ incol = facm * outcol + fact * ((one - texcol) * outcol * texcol + outcol * scr);
}
void mtex_rgb_linear(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol)
@@ -1121,25 +1157,25 @@ void mtex_rgb_linear(vec3 outcol, vec3 texcol, float fact, float facg, out vec3
fact *= facg;
if (texcol.r > 0.5)
- incol.r = outcol.r + fact*(2.0*(texcol.r - 0.5));
+ incol.r = outcol.r + fact * (2.0 * (texcol.r - 0.5));
else
- incol.r = outcol.r + fact*(2.0*(texcol.r) - 1.0);
+ incol.r = outcol.r + fact * (2.0 * (texcol.r) - 1.0);
if (texcol.g > 0.5)
- incol.g = outcol.g + fact*(2.0*(texcol.g - 0.5));
+ incol.g = outcol.g + fact * (2.0 * (texcol.g - 0.5));
else
- incol.g = outcol.g + fact*(2.0*(texcol.g) - 1.0);
+ incol.g = outcol.g + fact * (2.0 * (texcol.g) - 1.0);
if (texcol.b > 0.5)
- incol.b = outcol.b + fact*(2.0*(texcol.b - 0.5));
+ incol.b = outcol.b + fact * (2.0 * (texcol.b - 0.5));
else
- incol.b = outcol.b + fact*(2.0*(texcol.b) - 1.0);
+ incol.b = outcol.b + fact * (2.0 * (texcol.b) - 1.0);
}
void mtex_value_vars(inout float fact, float facg, out float facm)
{
fact *= abs(facg);
- facm = 1.0-fact;
+ facm = 1.0 - fact;
if (facg < 0.0) {
float tmp = fact;
@@ -1153,7 +1189,7 @@ void mtex_value_blend(float outcol, float texcol, float fact, float facg, out fl
float facm;
mtex_value_vars(fact, facg, facm);
- incol = fact*texcol + facm*outcol;
+ incol = fact * texcol + facm * outcol;
}
void mtex_value_mul(float outcol, float texcol, float fact, float facg, out float incol)
@@ -1162,7 +1198,7 @@ void mtex_value_mul(float outcol, float texcol, float fact, float facg, out floa
mtex_value_vars(fact, facg, facm);
facm = 1.0 - facg;
- incol = (facm + fact*texcol)*outcol;
+ incol = (facm + fact * texcol) * outcol;
}
void mtex_value_screen(float outcol, float texcol, float fact, float facg, out float incol)
@@ -1171,7 +1207,7 @@ void mtex_value_screen(float outcol, float texcol, float fact, float facg, out f
mtex_value_vars(fact, facg, facm);
facm = 1.0 - facg;
- incol = 1.0 - (facm + fact*(1.0 - texcol))*(1.0 - outcol);
+ incol = 1.0 - (facm + fact * (1.0 - texcol)) * (1.0 - outcol);
}
void mtex_value_sub(float outcol, float texcol, float fact, float facg, out float incol)
@@ -1180,7 +1216,7 @@ void mtex_value_sub(float outcol, float texcol, float fact, float facg, out floa
mtex_value_vars(fact, facg, facm);
fact = -fact;
- incol = fact*texcol + outcol;
+ incol = fact * texcol + outcol;
}
void mtex_value_add(float outcol, float texcol, float fact, float facg, out float incol)
@@ -1189,7 +1225,7 @@ void mtex_value_add(float outcol, float texcol, float fact, float facg, out floa
mtex_value_vars(fact, facg, facm);
fact = fact;
- incol = fact*texcol + outcol;
+ incol = fact * texcol + outcol;
}
void mtex_value_div(float outcol, float texcol, float fact, float facg, out float incol)
@@ -1198,7 +1234,7 @@ void mtex_value_div(float outcol, float texcol, float fact, float facg, out floa
mtex_value_vars(fact, facg, facm);
if (texcol != 0.0)
- incol = facm*outcol + fact*outcol/texcol;
+ incol = facm * outcol + fact * outcol / texcol;
else
incol = 0.0;
}
@@ -1208,7 +1244,7 @@ void mtex_value_diff(float outcol, float texcol, float fact, float facg, out flo
float facm;
mtex_value_vars(fact, facg, facm);
- incol = facm*outcol + fact*abs(texcol - outcol);
+ incol = facm * outcol + fact * abs(texcol - outcol);
}
void mtex_value_dark(float outcol, float texcol, float fact, float facg, out float incol)
@@ -1216,7 +1252,7 @@ void mtex_value_dark(float outcol, float texcol, float fact, float facg, out flo
float facm;
mtex_value_vars(fact, facg, facm);
- incol = facm*outcol + fact*min(outcol, texcol);
+ incol = facm * outcol + fact * min(outcol, texcol);
}
void mtex_value_light(float outcol, float texcol, float fact, float facg, out float incol)
@@ -1224,7 +1260,7 @@ void mtex_value_light(float outcol, float texcol, float fact, float facg, out fl
float facm;
mtex_value_vars(fact, facg, facm);
- float col = fact*texcol;
+ float col = fact * texcol;
if (col > outcol) incol = col; else incol = outcol;
}
@@ -1240,7 +1276,7 @@ void mtex_value_clamp(float fac, out float outfac)
void mtex_har_divide(float har, out float outhar)
{
- outhar = har/128.0;
+ outhar = har / 128.0;
}
void mtex_har_multiply_clamp(float har, out float outhar)
@@ -1285,15 +1321,15 @@ void mtex_rgb_invert(vec4 inrgb, out vec4 outrgb)
void mtex_value_stencil(float stencil, float intensity, out float outstencil, out float outintensity)
{
float fact = intensity;
- outintensity = intensity*stencil;
- outstencil = stencil*fact;
+ outintensity = intensity * stencil;
+ outstencil = stencil * fact;
}
void mtex_rgb_stencil(float stencil, vec4 rgb, out float outstencil, out vec4 outrgb)
{
float fact = rgb.a;
- outrgb = vec4(rgb.rgb, rgb.a*stencil);
- outstencil = stencil*fact;
+ outrgb = vec4(rgb.rgb, rgb.a * stencil);
+ outstencil = stencil * fact;
}
void mtex_mapping_ofs(vec3 texco, vec3 ofs, out vec3 outtexco)
@@ -1303,17 +1339,17 @@ void mtex_mapping_ofs(vec3 texco, vec3 ofs, out vec3 outtexco)
void mtex_mapping_size(vec3 texco, vec3 size, out vec3 outtexco)
{
- outtexco = size*texco;
+ outtexco = size * texco;
}
void mtex_2d_mapping(vec3 vec, out vec3 outvec)
{
- outvec = vec3(vec.xy*0.5 + vec2(0.5), vec.z);
+ outvec = vec3(vec.xy * 0.5 + vec2(0.5), vec.z);
}
vec3 mtex_2d_mapping(vec3 vec)
{
- return vec3(vec.xy*0.5 + vec2(0.5), vec.z);
+ return vec3(vec.xy * 0.5 + vec2(0.5), vec.z);
}
void mtex_cube_map(vec3 co, samplerCube ima, out float value, out vec4 color)
@@ -1347,10 +1383,10 @@ void mtex_normal(vec3 texco, sampler2D ima, out vec3 normal)
// the normal used points inward.
// Should this ever change this negate must be removed.
vec4 color = texture2D(ima, texco.xy);
- normal = 2.0*(vec3(-color.r, color.g, color.b) - vec3(-0.5, 0.5, 0.5));
+ normal = 2.0 * (vec3(-color.r, color.g, color.b) - vec3(-0.5, 0.5, 0.5));
}
-void mtex_bump_normals_init( vec3 vN, out vec3 vNorg, out vec3 vNacc, out float fPrevMagnitude )
+void mtex_bump_normals_init(vec3 vN, out vec3 vNorg, out vec3 vNacc, out float fPrevMagnitude)
{
vNorg = vN;
vNacc = vN;
@@ -1376,20 +1412,20 @@ void mtex_bump_init_objspace(
{
mat3 obj2view = to_mat3(gl_ModelViewMatrix);
mat3 view2obj = to_mat3(gl_ModelViewMatrixInverse);
-
- vec3 vSigmaS = view2obj * dFdx( surf_pos );
- vec3 vSigmaT = view2obj * dFdy( surf_pos );
- vec3 vN = normalize( surf_norm * obj2view );
- vR1 = cross( vSigmaT, vN );
- vR2 = cross( vN, vSigmaS ) ;
- fDet = dot ( vSigmaS, vR1 );
-
+ vec3 vSigmaS = view2obj * dFdx(surf_pos);
+ vec3 vSigmaT = view2obj * dFdy(surf_pos);
+ vec3 vN = normalize(surf_norm * obj2view);
+
+ vR1 = cross(vSigmaT, vN);
+ vR2 = cross(vN, vSigmaS);
+ fDet = dot(vSigmaS, vR1);
+
/* pretransform vNacc (in mtex_bump_apply) using the inverse transposed */
vR1 = vR1 * view2obj;
vR2 = vR2 * view2obj;
vN = vN * view2obj;
-
+
float fMagnitude = abs(fDet) * length(vN);
vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in);
fPrevMagnitude_out = fMagnitude;
@@ -1401,14 +1437,14 @@ void mtex_bump_init_texturespace(
out float fPrevMagnitude_out, out vec3 vNacc_out,
out vec3 vR1, out vec3 vR2, out float fDet)
{
- vec3 vSigmaS = dFdx( surf_pos );
- vec3 vSigmaT = dFdy( surf_pos );
+ vec3 vSigmaS = dFdx(surf_pos);
+ vec3 vSigmaT = dFdy(surf_pos);
vec3 vN = surf_norm; /* normalized interpolated vertex normal */
-
- vR1 = normalize( cross( vSigmaT, vN ) );
- vR2 = normalize( cross( vN, vSigmaS ) );
- fDet = sign( dot(vSigmaS, vR1) );
-
+
+ vR1 = normalize(cross(vSigmaT, vN));
+ vR2 = normalize(cross(vN, vSigmaS));
+ fDet = sign(dot(vSigmaS, vR1));
+
float fMagnitude = abs(fDet);
vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in);
fPrevMagnitude_out = fMagnitude;
@@ -1420,14 +1456,14 @@ void mtex_bump_init_viewspace(
out float fPrevMagnitude_out, out vec3 vNacc_out,
out vec3 vR1, out vec3 vR2, out float fDet)
{
- vec3 vSigmaS = dFdx( surf_pos );
- vec3 vSigmaT = dFdy( surf_pos );
+ vec3 vSigmaS = dFdx(surf_pos);
+ vec3 vSigmaT = dFdy(surf_pos);
vec3 vN = surf_norm; /* normalized interpolated vertex normal */
-
- vR1 = cross( vSigmaT, vN );
- vR2 = cross( vN, vSigmaS ) ;
- fDet = dot ( vSigmaS, vR1 );
-
+
+ vR1 = cross(vSigmaT, vN);
+ vR2 = cross(vN, vSigmaS);
+ fDet = dot(vSigmaS, vR1);
+
float fMagnitude = abs(fDet);
vNacc_out = vNacc_in * (fMagnitude / fPrevMagnitude_in);
fPrevMagnitude_out = fMagnitude;
@@ -1438,14 +1474,14 @@ void mtex_bump_tap3(
out float dBs, out float dBt)
{
vec2 STll = texco.xy;
- vec2 STlr = texco.xy + dFdx(texco.xy) ;
- vec2 STul = texco.xy + dFdy(texco.xy) ;
-
- float Hll,Hlr,Hul;
- rgbtobw( texture2D(ima, STll), Hll );
- rgbtobw( texture2D(ima, STlr), Hlr );
- rgbtobw( texture2D(ima, STul), Hul );
-
+ vec2 STlr = texco.xy + dFdx(texco.xy);
+ vec2 STul = texco.xy + dFdy(texco.xy);
+
+ float Hll, Hlr, Hul;
+ rgbtobw(texture2D(ima, STll), Hll);
+ rgbtobw(texture2D(ima, STlr), Hlr);
+ rgbtobw(texture2D(ima, STul), Hul);
+
dBs = hScale * (Hlr - Hll);
dBt = hScale * (Hul - Hll);
}
@@ -1460,83 +1496,82 @@ void mtex_bump_bicubic(
float Hr;
float Hd;
float Hu;
-
+
vec2 TexDx = dFdx(texco.xy);
vec2 TexDy = dFdy(texco.xy);
-
- vec2 STl = texco.xy - 0.5 * TexDx ;
- vec2 STr = texco.xy + 0.5 * TexDx ;
- vec2 STd = texco.xy - 0.5 * TexDy ;
- vec2 STu = texco.xy + 0.5 * TexDy ;
-
+
+ vec2 STl = texco.xy - 0.5 * TexDx;
+ vec2 STr = texco.xy + 0.5 * TexDx;
+ vec2 STd = texco.xy - 0.5 * TexDy;
+ vec2 STu = texco.xy + 0.5 * TexDy;
+
rgbtobw(texture2D(ima, STl), Hl);
rgbtobw(texture2D(ima, STr), Hr);
rgbtobw(texture2D(ima, STd), Hd);
rgbtobw(texture2D(ima, STu), Hu);
-
+
vec2 dHdxy = vec2(Hr - Hl, Hu - Hd);
- float fBlend = clamp(1.0-textureQueryLOD(ima, texco.xy).x, 0.0, 1.0);
- if (fBlend!=0.0)
- {
+ float fBlend = clamp(1.0 - textureQueryLOD(ima, texco.xy).x, 0.0, 1.0);
+ if (fBlend != 0.0) {
// the derivative of the bicubic sampling of level 0
ivec2 vDim;
vDim = textureSize(ima, 0);
// taking the fract part of the texture coordinate is a hardcoded wrap mode.
- // this is acceptable as textures use wrap mode exclusively in 3D view elsewhere in blender.
+ // this is acceptable as textures use wrap mode exclusively in 3D view elsewhere in blender.
// this is done so that we can still get a valid texel with uvs outside the 0,1 range
// by texelFetch below, as coordinates are clamped when using this function.
- vec2 fTexLoc = vDim*fract(texco.xy) - vec2(0.5, 0.5);
+ vec2 fTexLoc = vDim * fract(texco.xy) - vec2(0.5, 0.5);
ivec2 iTexLoc = ivec2(floor(fTexLoc));
- vec2 t = clamp(fTexLoc - iTexLoc, 0.0, 1.0); // sat just to be pedantic
+ vec2 t = clamp(fTexLoc - iTexLoc, 0.0, 1.0); // sat just to be pedantic
/*******************************************************************************************
* This block will replace the one below when one channel textures are properly supported. *
*******************************************************************************************
- vec4 vSamplesUL = textureGather(ima, (iTexLoc+ivec2(-1,-1) + vec2(0.5,0.5))/vDim );
- vec4 vSamplesUR = textureGather(ima, (iTexLoc+ivec2(1,-1) + vec2(0.5,0.5))/vDim );
- vec4 vSamplesLL = textureGather(ima, (iTexLoc+ivec2(-1,1) + vec2(0.5,0.5))/vDim );
- vec4 vSamplesLR = textureGather(ima, (iTexLoc+ivec2(1,1) + vec2(0.5,0.5))/vDim );
+ vec4 vSamplesUL = textureGather(ima, (iTexLoc+ivec2(-1,-1) + vec2(0.5,0.5))/vDim);
+ vec4 vSamplesUR = textureGather(ima, (iTexLoc+ivec2(1,-1) + vec2(0.5,0.5))/vDim);
+ vec4 vSamplesLL = textureGather(ima, (iTexLoc+ivec2(-1,1) + vec2(0.5,0.5))/vDim);
+ vec4 vSamplesLR = textureGather(ima, (iTexLoc+ivec2(1,1) + vec2(0.5,0.5))/vDim);
mat4 H = mat4(vSamplesUL.w, vSamplesUL.x, vSamplesLL.w, vSamplesLL.x,
- vSamplesUL.z, vSamplesUL.y, vSamplesLL.z, vSamplesLL.y,
- vSamplesUR.w, vSamplesUR.x, vSamplesLR.w, vSamplesLR.x,
- vSamplesUR.z, vSamplesUR.y, vSamplesLR.z, vSamplesLR.y);
-*/
+ vSamplesUL.z, vSamplesUL.y, vSamplesLL.z, vSamplesLL.y,
+ vSamplesUR.w, vSamplesUR.x, vSamplesLR.w, vSamplesLR.x,
+ vSamplesUR.z, vSamplesUR.y, vSamplesLR.z, vSamplesLR.y);
+ */
ivec2 iTexLocMod = iTexLoc + ivec2(-1, -1);
mat4 H;
-
+
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
- ivec2 iTexTmp = iTexLocMod + ivec2(i,j);
-
+ ivec2 iTexTmp = iTexLocMod + ivec2(i, j);
+
// wrap texture coordinates manually for texelFetch to work on uvs oitside the 0,1 range.
// this is guaranteed to work since we take the fractional part of the uv above.
- iTexTmp.x = (iTexTmp.x < 0)? iTexTmp.x + vDim.x : ((iTexTmp.x >= vDim.x)? iTexTmp.x - vDim.x : iTexTmp.x);
- iTexTmp.y = (iTexTmp.y < 0)? iTexTmp.y + vDim.y : ((iTexTmp.y >= vDim.y)? iTexTmp.y - vDim.y : iTexTmp.y);
+ iTexTmp.x = (iTexTmp.x < 0) ? iTexTmp.x + vDim.x : ((iTexTmp.x >= vDim.x) ? iTexTmp.x - vDim.x : iTexTmp.x);
+ iTexTmp.y = (iTexTmp.y < 0) ? iTexTmp.y + vDim.y : ((iTexTmp.y >= vDim.y) ? iTexTmp.y - vDim.y : iTexTmp.y);
rgbtobw(texelFetch(ima, iTexTmp, 0), H[i][j]);
}
}
-
+
float x = t.x, y = t.y;
float x2 = x * x, x3 = x2 * x, y2 = y * y, y3 = y2 * y;
- vec4 X = vec4(-0.5*(x3+x)+x2, 1.5*x3-2.5*x2+1, -1.5*x3+2*x2+0.5*x, 0.5*(x3-x2));
- vec4 Y = vec4(-0.5*(y3+y)+y2, 1.5*y3-2.5*y2+1, -1.5*y3+2*y2+0.5*y, 0.5*(y3-y2));
- vec4 dX = vec4(-1.5*x2+2*x-0.5, 4.5*x2-5*x, -4.5*x2+4*x+0.5, 1.5*x2-x);
- vec4 dY = vec4(-1.5*y2+2*y-0.5, 4.5*y2-5*y, -4.5*y2+4*y+0.5, 1.5*y2-y);
-
+ vec4 X = vec4(-0.5 * (x3 + x) + x2, 1.5 * x3 - 2.5 * x2 + 1, -1.5 * x3 + 2 * x2 + 0.5 * x, 0.5 * (x3 - x2));
+ vec4 Y = vec4(-0.5 * (y3 + y) + y2, 1.5 * y3 - 2.5 * y2 + 1, -1.5 * y3 + 2 * y2 + 0.5 * y, 0.5 * (y3 - y2));
+ vec4 dX = vec4(-1.5 * x2 + 2 * x - 0.5, 4.5 * x2 - 5 * x, -4.5 * x2 + 4 * x + 0.5, 1.5 * x2 - x);
+ vec4 dY = vec4(-1.5 * y2 + 2 * y - 0.5, 4.5 * y2 - 5 * y, -4.5 * y2 + 4 * y + 0.5, 1.5 * y2 - y);
+
// complete derivative in normalized coordinates (mul by vDim)
vec2 dHdST = vDim * vec2(dot(Y, H * dX), dot(dY, H * X));
// transform derivative to screen-space
- vec2 dHdxy_bicubic = vec2( dHdST.x * TexDx.x + dHdST.y * TexDx.y,
- dHdST.x * TexDy.x + dHdST.y * TexDy.y );
+ vec2 dHdxy_bicubic = vec2(dHdST.x * TexDx.x + dHdST.y * TexDx.y,
+ dHdST.x * TexDy.x + dHdST.y * TexDy.y);
// blend between the two
- dHdxy = dHdxy*(1-fBlend) + dHdxy_bicubic*fBlend;
+ dHdxy = dHdxy * (1 - fBlend) + dHdxy_bicubic * fBlend;
}
dBs = hScale * dHdxy.x;
@@ -1553,18 +1588,18 @@ void mtex_bump_tap5(
vec2 TexDy = dFdy(texco.xy);
vec2 STc = texco.xy;
- vec2 STl = texco.xy - 0.5 * TexDx ;
- vec2 STr = texco.xy + 0.5 * TexDx ;
- vec2 STd = texco.xy - 0.5 * TexDy ;
- vec2 STu = texco.xy + 0.5 * TexDy ;
-
- float Hc,Hl,Hr,Hd,Hu;
- rgbtobw( texture2D(ima, STc), Hc );
- rgbtobw( texture2D(ima, STl), Hl );
- rgbtobw( texture2D(ima, STr), Hr );
- rgbtobw( texture2D(ima, STd), Hd );
- rgbtobw( texture2D(ima, STu), Hu );
-
+ vec2 STl = texco.xy - 0.5 * TexDx;
+ vec2 STr = texco.xy + 0.5 * TexDx;
+ vec2 STd = texco.xy - 0.5 * TexDy;
+ vec2 STu = texco.xy + 0.5 * TexDy;
+
+ float Hc, Hl, Hr, Hd, Hu;
+ rgbtobw(texture2D(ima, STc), Hc);
+ rgbtobw(texture2D(ima, STl), Hl);
+ rgbtobw(texture2D(ima, STr), Hr);
+ rgbtobw(texture2D(ima, STd), Hd);
+ rgbtobw(texture2D(ima, STu), Hu);
+
dBs = hScale * (Hr - Hl);
dBt = hScale * (Hu - Hd);
}
@@ -1573,27 +1608,27 @@ void mtex_bump_deriv(
vec3 texco, sampler2D ima, float ima_x, float ima_y, float hScale,
out float dBs, out float dBt)
{
- float s = 1.0; // negate this if flipped texture coordinate
+ float s = 1.0; // negate this if flipped texture coordinate
vec2 TexDx = dFdx(texco.xy);
vec2 TexDy = dFdy(texco.xy);
-
+
// this variant using a derivative map is described here
// http://mmikkelsen3d.blogspot.com/2011/07/derivative-maps.html
vec2 dim = vec2(ima_x, ima_y);
- vec2 dBduv = hScale*dim*(2.0*texture2D(ima, texco.xy).xy-1.0);
-
- dBs = dBduv.x*TexDx.x + s*dBduv.y*TexDx.y;
- dBt = dBduv.x*TexDy.x + s*dBduv.y*TexDy.y;
+ vec2 dBduv = hScale * dim * (2.0 * texture2D(ima, texco.xy).xy - 1.0);
+
+ dBs = dBduv.x * TexDx.x + s * dBduv.y * TexDx.y;
+ dBt = dBduv.x * TexDy.x + s * dBduv.y * TexDy.y;
}
void mtex_bump_apply(
float fDet, float dBs, float dBt, vec3 vR1, vec3 vR2, vec3 vNacc_in,
out vec3 vNacc_out, out vec3 perturbed_norm)
{
- vec3 vSurfGrad = sign(fDet) * ( dBs * vR1 + dBt * vR2 );
-
+ vec3 vSurfGrad = sign(fDet) * (dBs * vR1 + dBt * vR2);
+
vNacc_out = vNacc_in - vSurfGrad;
- perturbed_norm = normalize( vNacc_out );
+ perturbed_norm = normalize(vNacc_out);
}
void mtex_bump_apply_texspace(
@@ -1604,12 +1639,12 @@ void mtex_bump_apply_texspace(
vec2 TexDx = dFdx(texco.xy);
vec2 TexDy = dFdy(texco.xy);
- vec3 vSurfGrad = sign(fDet) * (
- dBs / length( vec2(ima_x*TexDx.x, ima_y*TexDx.y) ) * vR1 +
- dBt / length( vec2(ima_x*TexDy.x, ima_y*TexDy.y) ) * vR2 );
+ vec3 vSurfGrad = sign(fDet) * (
+ dBs / length(vec2(ima_x * TexDx.x, ima_y * TexDx.y)) * vR1 +
+ dBt / length(vec2(ima_x * TexDy.x, ima_y * TexDy.y)) * vR2);
vNacc_out = vNacc_in - vSurfGrad;
- perturbed_norm = normalize( vNacc_out );
+ perturbed_norm = normalize(vNacc_out);
}
void mtex_negate_texnormal(vec3 normal, out vec3 outnormal)
@@ -1621,13 +1656,13 @@ void mtex_nspace_tangent(vec4 tangent, vec3 normal, vec3 texnormal, out vec3 out
{
vec3 B = tangent.w * cross(normal, tangent.xyz);
- outnormal = texnormal.x*tangent.xyz + texnormal.y*B + texnormal.z*normal;
+ outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal;
outnormal = normalize(outnormal);
}
void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal)
{
- outnormal = normalize((viewmat*vec4(texnormal, 0.0)).xyz);
+ outnormal = normalize((viewmat * vec4(texnormal, 0.0)).xyz);
}
void mtex_nspace_object(vec3 texnormal, out vec3 outnormal)
@@ -1637,7 +1672,7 @@ void mtex_nspace_object(vec3 texnormal, out vec3 outnormal)
void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal)
{
- outnormal = (1.0 - norfac)*normal + norfac*newnormal;
+ outnormal = (1.0 - norfac) * normal + norfac * newnormal;
outnormal = normalize(outnormal);
}
@@ -1660,26 +1695,26 @@ void lamp_visibility_other(vec3 co, vec3 lampco, out vec3 lv, out float dist, ou
void lamp_falloff_invlinear(float lampdist, float dist, out float visifac)
{
- visifac = lampdist/(lampdist + dist);
+ visifac = lampdist / (lampdist + dist);
}
void lamp_falloff_invsquare(float lampdist, float dist, out float visifac)
{
- visifac = lampdist/(lampdist + dist*dist);
+ visifac = lampdist / (lampdist + dist * dist);
}
void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out float visifac)
{
- float lampdistkw = lampdist*lampdist;
+ float lampdistkw = lampdist * lampdist;
- visifac = lampdist/(lampdist + ld1*dist);
- visifac *= lampdistkw/(lampdistkw + ld2*dist*dist);
+ visifac = lampdist / (lampdist + ld1 * dist);
+ visifac *= lampdistkw / (lampdistkw + ld2 * dist * dist);
}
void lamp_falloff_invcoefficients(float coeff_const, float coeff_lin, float coeff_quad, float dist, out float visifac)
{
vec3 coeff = vec3(coeff_const, coeff_lin, coeff_quad);
- vec3 d_coeff = vec3(1.0, dist, dist*dist);
+ vec3 d_coeff = vec3(1.0, dist, dist * dist);
float visifac_r = dot(coeff, d_coeff);
if (visifac_r > 0.0)
visifac = 1.0 / visifac_r;
@@ -1689,25 +1724,25 @@ void lamp_falloff_invcoefficients(float coeff_const, float coeff_lin, float coef
void lamp_falloff_curve(float lampdist, sampler2D curvemap, float dist, out float visifac)
{
- visifac = texture2D(curvemap, vec2(dist/lampdist, 0.0)).x;
+ visifac = texture2D(curvemap, vec2(dist / lampdist, 0.0)).x;
}
void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac)
{
- float t= lampdist - dist;
+ float t = lampdist - dist;
- outvisifac= visifac*max(t, 0.0)/lampdist;
+ outvisifac = visifac * max(t, 0.0) / lampdist;
}
void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec2 scale, vec3 lv, out float inpr)
{
if (dot(lv, lampvec) > 0.0) {
- vec3 lvrot = (lampimat*vec4(lv, 0.0)).xyz;
+ vec3 lvrot = (lampimat * vec4(lv, 0.0)).xyz;
/* without clever non-uniform scale, we could do: */
// float x = max(abs(lvrot.x / lvrot.z), abs(lvrot.y / lvrot.z));
float x = max(abs((lvrot.x / scale.x) / lvrot.z), abs((lvrot.y / scale.y) / lvrot.z));
- inpr = 1.0/sqrt(1.0 + x*x);
+ inpr = 1.0 / sqrt(1.0 + x * x);
}
else
inpr = 0.0;
@@ -1742,15 +1777,15 @@ void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac,
/* soft area */
if (spotbl != 0.0)
- inpr *= smoothstep(0.0, 1.0, t/spotbl);
+ inpr *= smoothstep(0.0, 1.0, t / spotbl);
- outvisifac = visifac*inpr;
+ outvisifac = visifac * inpr;
}
}
void lamp_visibility_clamp(float visifac, out float outvisifac)
{
- outvisifac = (visifac < 0.001)? 0.0: visifac;
+ outvisifac = (visifac < 0.001) ? 0.0 : visifac;
}
void world_paper_view(vec3 vec, out vec3 outvec)
@@ -1790,7 +1825,7 @@ void world_blend(vec3 vec, out float blend)
void shade_view(vec3 co, out vec3 view)
{
/* handle perspective/orthographic */
- view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(co): vec3(0.0, 0.0, -1.0);
+ view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(co) : vec3(0.0, 0.0, -1.0);
}
void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn)
@@ -1813,14 +1848,14 @@ void shade_is_no_diffuse(out float is)
void shade_is_hemi(float inp, out float is)
{
- is = 0.5*inp + 0.5;
+ is = 0.5 * inp + 0.5;
}
float area_lamp_energy(mat4 area, vec3 co, vec3 vn)
{
vec3 vec[4], c[4];
float rad[4], fac;
-
+
vec[0] = normalize(co - area[0].xyz);
vec[1] = normalize(co - area[1].xyz);
vec[2] = normalize(co - area[2].xyz);
@@ -1836,10 +1871,10 @@ float area_lamp_energy(mat4 area, vec3 co, vec3 vn)
rad[2] = acos(dot(vec[2], vec[3]));
rad[3] = acos(dot(vec[3], vec[0]));
- fac= rad[0]*dot(vn, c[0]);
- fac+= rad[1]*dot(vn, c[1]);
- fac+= rad[2]*dot(vn, c[2]);
- fac+= rad[3]*dot(vn, c[3]);
+ fac = rad[0] * dot(vn, c[0]);
+ fac += rad[1] * dot(vn, c[1]);
+ fac += rad[2] * dot(vn, c[2]);
+ fac += rad[3] * dot(vn, c[3]);
return max(fac, 0.0);
}
@@ -1857,7 +1892,7 @@ void shade_inp_area(
else {
float intens = area_lamp_energy(area, co, vn);
- inp = pow(intens*areasize, k);
+ inp = pow(intens * areasize, k);
}
}
@@ -1879,8 +1914,8 @@ void shade_diffuse_oren_nayer(float nl, vec3 n, vec3 l, vec3 v, float rough, out
float Lit_A = acos(realnl);
float View_A = acos(nv);
- vec3 Lit_B = normalize(l - realnl*n);
- vec3 View_B = normalize(v - nv*n);
+ vec3 Lit_B = normalize(l - realnl * n);
+ vec3 View_B = normalize(v - nv * n);
float t = max(dot(Lit_B, View_B), 0.0);
@@ -1895,11 +1930,11 @@ void shade_diffuse_oren_nayer(float nl, vec3 n, vec3 l, vec3 v, float rough, out
b = Lit_A;
}
- float A = 1.0 - (0.5*((rough*rough)/((rough*rough) + 0.33)));
- float B = 0.45*((rough*rough)/((rough*rough) + 0.09));
+ float A = 1.0 - (0.5 * ((rough * rough) / ((rough * rough) + 0.33)));
+ float B = 0.45 * ((rough * rough) / ((rough * rough) + 0.09));
b *= 0.95;
- is = nl*(A + (B * t * sin(a) * tan(b)));
+ is = nl * (A + (B * t * sin(a) * tan(b)));
}
}
@@ -1910,7 +1945,7 @@ void shade_diffuse_toon(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out f
if (ang < size) is = 1.0;
else if (ang > (size + tsmooth) || tsmooth == 0.0) is = 0.0;
- else is = 1.0 - ((ang - size)/tsmooth);
+ else is = 1.0 - ((ang - size) / tsmooth);
}
void shade_diffuse_minnaert(float nl, vec3 n, vec3 v, float darkness, out float is)
@@ -1922,9 +1957,9 @@ void shade_diffuse_minnaert(float nl, vec3 n, vec3 v, float darkness, out float
float nv = max(dot(n, v), 0.0);
if (darkness <= 1.0)
- is = nl*pow(max(nv*nl, 0.1), darkness - 1.0);
+ is = nl * pow(max(nv * nl, 0.1), darkness - 1.0);
else
- is = nl*pow(1.0001 - nv, darkness - 1.0);
+ is = nl * pow(1.0001 - nv, darkness - 1.0);
}
}
@@ -1933,18 +1968,18 @@ float fresnel_fac(vec3 view, vec3 vn, float grad, float fac)
float t1, t2;
float ffac;
- if (fac==0.0) {
+ if (fac == 0.0) {
ffac = 1.0;
}
else {
- t1= dot(view, vn);
- if (t1>0.0) t2= 1.0+t1;
- else t2= 1.0-t1;
+ t1 = dot(view, vn);
+ if (t1 > 0.0) t2 = 1.0 + t1;
+ else t2 = 1.0 - t1;
- t2= grad + (1.0-grad)*pow(t2, fac);
+ t2 = grad + (1.0 - grad) * pow(t2, fac);
- if (t2<0.0) ffac = 0.0;
- else if (t2>1.0) ffac = 1.0;
+ if (t2 < 0.0) ffac = 0.0;
+ else if (t2 > 1.0) ffac = 1.0;
else ffac = t2;
}
@@ -1958,18 +1993,18 @@ void shade_diffuse_fresnel(vec3 vn, vec3 lv, vec3 view, float fac_i, float fac,
void shade_cubic(float is, out float outis)
{
- if (is>0.0 && is<1.0)
- outis= smoothstep(0.0, 1.0, is);
+ if (is > 0.0 && is < 1.0)
+ outis = smoothstep(0.0, 1.0, is);
else
- outis= is;
+ outis = is;
}
void shade_visifac(float i, float visifac, float refl, out float outi)
{
/*if (i > 0.0)*/
- outi = max(i*visifac*refl, 0.0);
+ outi = max(i * visifac * refl, 0.0);
/*else
- outi = i;*/
+ outi = i;*/
}
void shade_tangent_v_spec(vec3 tang, out vec3 vn)
@@ -1980,7 +2015,7 @@ void shade_tangent_v_spec(vec3 tang, out vec3 vn)
void shade_add_to_diffuse(float i, vec3 lampcol, vec3 col, out vec3 outcol)
{
if (i > 0.0)
- outcol = i*lampcol*col;
+ outcol = i * lampcol * col;
else
outcol = vec3(0.0, 0.0, 0.0);
}
@@ -1991,9 +2026,9 @@ void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float
lv = normalize(lv);
t = dot(vn, lv);
- t = 0.5*t + 0.5;
+ t = 0.5 * t + 0.5;
- t = visifac*spec*pow(t, hard);
+ t = visifac * spec * pow(t, hard);
}
void shade_phong_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac)
@@ -2016,7 +2051,7 @@ void shade_cooktorr_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac)
float nv = max(dot(n, v), 0.0);
float i = pow(nh, hard);
- i = i/(0.1+nv);
+ i = i / (0.1 + nv);
specfac = i;
}
}
@@ -2030,10 +2065,10 @@ void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, ou
specfac = 0.0;
}
else {
- if (spec_power<100.0)
- spec_power= sqrt(1.0/spec_power);
+ if (spec_power < 100.0)
+ spec_power = sqrt(1.0 / spec_power);
else
- spec_power= 10.0/spec_power;
+ spec_power = 10.0 / spec_power;
vec3 h = normalize(v + l);
float nh = dot(n, h);
@@ -2050,8 +2085,8 @@ void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, ou
float vh = max(dot(v, h), 0.01);
float a = 1.0;
- float b = (2.0*nh*nv)/vh;
- float c = (2.0*nh*nl)/vh;
+ float b = (2.0 * nh * nv) / vh;
+ float c = (2.0 * nh * nl) / vh;
float g = 0.0;
@@ -2065,7 +2100,7 @@ void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, ou
(((vh * (p - vh)) + 1.0) * ((vh * (p - vh)) + 1.0)))));
float ang = acos(nh);
- specfac = max(f*g*exp_blender((-(ang*ang)/(2.0*spec_power*spec_power))), 0.0);
+ specfac = max(f * g * exp_blender((-(ang * ang) / (2.0 * spec_power * spec_power))), 0.0);
}
}
}
@@ -2080,7 +2115,7 @@ void shade_wardiso_spec(vec3 n, vec3 l, vec3 v, float rms, out float specfac)
float angle = tan(acos(nh));
float alpha = max(rms, 0.001);
- specfac= nl * (1.0/(4.0*M_PI*alpha*alpha))*(exp_blender(-(angle*angle)/(alpha*alpha))/(sqrt(nv*nl)));
+ specfac = nl * (1.0 / (4.0 * M_PI * alpha * alpha)) * (exp_blender(-(angle * angle) / (alpha * alpha)) / (sqrt(nv * nl)));
}
void shade_toon_spec(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float specfac)
@@ -2091,24 +2126,24 @@ void shade_toon_spec(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out floa
if (ang < size) rslt = 1.0;
else if (ang >= (size + tsmooth) || tsmooth == 0.0) rslt = 0.0;
- else rslt = 1.0 - ((ang - size)/tsmooth);
+ else rslt = 1.0 - ((ang - size) / tsmooth);
specfac = rslt;
}
void shade_spec_area_inp(float specfac, float inp, out float outspecfac)
{
- outspecfac = specfac*inp;
+ outspecfac = specfac * inp;
}
void shade_spec_t(float shadfac, float spec, float visifac, float specfac, out float t)
{
- t = shadfac*spec*visifac*specfac;
+ t = shadfac * spec * visifac * specfac;
}
void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol)
{
- outcol = t*lampcol*speccol;
+ outcol = t * lampcol * speccol;
}
void shade_add_mirror(vec3 mir, vec4 refcol, vec3 combined, out vec3 result)
@@ -2134,7 +2169,7 @@ void shade_add(vec4 col1, vec4 col2, out vec4 outcol)
void shade_madd(vec4 col, vec4 col1, vec4 col2, out vec4 outcol)
{
- outcol = col + col1*col2;
+ outcol = col + col1 * col2;
}
void shade_add_clamped(vec4 col1, vec4 col2, out vec4 outcol)
@@ -2144,52 +2179,52 @@ void shade_add_clamped(vec4 col1, vec4 col2, out vec4 outcol)
void shade_madd_clamped(vec4 col, vec4 col1, vec4 col2, out vec4 outcol)
{
- outcol = col + max(col1*col2, vec4(0.0, 0.0, 0.0, 0.0));
+ outcol = col + max(col1 * col2, vec4(0.0, 0.0, 0.0, 0.0));
}
void shade_maddf(vec4 col, float f, vec4 col1, out vec4 outcol)
{
- outcol = col + f*col1;
+ outcol = col + f * col1;
}
void shade_mul(vec4 col1, vec4 col2, out vec4 outcol)
{
- outcol = col1*col2;
+ outcol = col1 * col2;
}
void shade_mul_value(float fac, vec4 col, out vec4 outcol)
{
- outcol = col*fac;
+ outcol = col * fac;
}
void shade_mul_value_v3(float fac, vec3 col, out vec3 outcol)
{
- outcol = col*fac;
+ outcol = col * fac;
}
void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
{
- outcol = vec4(col.rgb*obcol.rgb, col.a);
+ outcol = vec4(col.rgb * obcol.rgb, col.a);
}
void ramp_rgbtobw(vec3 color, out float outval)
{
- outval = color.r*0.3 + color.g*0.58 + color.b*0.12;
+ outval = color.r * 0.3 + color.g * 0.58 + color.b * 0.12;
}
void shade_only_shadow(float i, float shadfac, float energy, vec3 shadcol, out vec3 outshadrgb)
{
- outshadrgb = i*energy*(1.0 - shadfac)*(vec3(1.0)-shadcol);
+ outshadrgb = i * energy * (1.0 - shadfac) * (vec3(1.0) - shadcol);
}
void shade_only_shadow_diffuse(vec3 shadrgb, vec3 rgb, vec4 diff, out vec4 outdiff)
{
- outdiff = diff - vec4(rgb*shadrgb, 0.0);
+ outdiff = diff - vec4(rgb * shadrgb, 0.0);
}
void shade_only_shadow_specular(vec3 shadrgb, vec3 specrgb, vec4 spec, out vec4 outspec)
{
- outspec = spec - vec4(specrgb*shadrgb, 0.0);
+ outspec = spec - vec4(specrgb * shadrgb, 0.0);
}
void shade_clamp_positive(vec4 col, out vec4 outcol)
@@ -2205,12 +2240,12 @@ void test_shadowbuf(
result = 0.0;
}
else {
- vec4 co = shadowpersmat*vec4(rco, 1.0);
+ vec4 co = shadowpersmat * vec4(rco, 1.0);
//float bias = (1.5 - inp*inp)*shadowbias;
- co.z -= shadowbias*co.w;
-
- if (co.w > 0.0 && co.x > 0.0 && co.x/co.w < 1.0 && co.y > 0.0 && co.y/co.w < 1.0)
+ co.z -= shadowbias * co.w;
+
+ if (co.w > 0.0 && co.x > 0.0 && co.x / co.w < 1.0 && co.y > 0.0 && co.y / co.w < 1.0)
result = shadow2DProj(shadowmap, co).x;
else
result = 1.0;
@@ -2225,23 +2260,23 @@ void test_shadowbuf_vsm(
result = 0.0;
}
else {
- vec4 co = shadowpersmat*vec4(rco, 1.0);
- if (co.w > 0.0 && co.x > 0.0 && co.x/co.w < 1.0 && co.y > 0.0 && co.y/co.w < 1.0) {
+ vec4 co = shadowpersmat * vec4(rco, 1.0);
+ if (co.w > 0.0 && co.x > 0.0 && co.x / co.w < 1.0 && co.y > 0.0 && co.y / co.w < 1.0) {
vec2 moments = texture2DProj(shadowmap, co).rg;
- float dist = co.z/co.w;
+ float dist = co.z / co.w;
float p = 0.0;
-
+
if (dist <= moments.x)
p = 1.0;
- float variance = moments.y - (moments.x*moments.x);
- variance = max(variance, shadowbias/10.0);
+ float variance = moments.y - (moments.x * moments.x);
+ variance = max(variance, shadowbias / 10.0);
float d = moments.x - dist;
- float p_max = variance / (variance + d*d);
+ float p_max = variance / (variance + d * d);
// Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1]
- p_max = clamp((p_max-bleedbias)/(1.0-bleedbias), 0.0, 1.0);
+ p_max = clamp((p_max - bleedbias) / (1.0 - bleedbias), 0.0, 1.0);
result = max(p, p_max);
}
@@ -2284,14 +2319,14 @@ void shadows_only_vsm(
void shade_light_texture(vec3 rco, sampler2D cookie, mat4 shadowpersmat, out vec4 result)
{
- vec4 co = shadowpersmat*vec4(rco, 1.0);
+ vec4 co = shadowpersmat * vec4(rco, 1.0);
result = texture2DProj(cookie, co);
}
void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outcol)
{
- outcol = linfac*(1.0 - exp(col*logfac));
+ outcol = linfac * (1.0 - exp(col * logfac));
}
void shade_mist_factor(
@@ -2301,11 +2336,11 @@ void shade_mist_factor(
if (enable == 1.0) {
float fac, zcor;
- zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2];
-
+ zcor = (gl_ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2];
+
fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0);
if (misttype == 0.0) fac *= fac;
- else if (misttype == 1.0);
+ else if (misttype == 1.0) ;
else fac = sqrt(fac);
outfac = 1.0 - (1.0 - fac) * (1.0 - misi);
@@ -2328,7 +2363,7 @@ void shade_alpha_opaque(vec4 col, out vec4 outcol)
void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
{
- outcol = vec4(col.rgb, col.a*obcol.a);
+ outcol = vec4(col.rgb, col.a * obcol.a);
}
/*********** NEW SHADER UTILITIES **************/
@@ -2343,9 +2378,9 @@ float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
if (g > 0.0) {
g = sqrt(g);
- float A =(g - c)/(g + c);
- float B =(c *(g + c)- 1.0)/(c *(g - c)+ 1.0);
- result = 0.5 * A * A *(1.0 + B * B);
+ float A = (g - c) / (g + c);
+ float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0);
+ result = 0.5 * A * A * (1.0 + B * B);
}
else {
result = 1.0; /* TIR (no refracted component) */
@@ -2356,7 +2391,7 @@ float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
float hypot(float x, float y)
{
- return sqrt(x*x + y*y);
+ return sqrt(x * x + y * y);
}
void generated_from_orco(vec3 orco, out vec3 generated)
@@ -2364,6 +2399,17 @@ void generated_from_orco(vec3 orco, out vec3 generated)
generated = orco * 0.5 + vec3(0.5);
}
+int floor_to_int(float x)
+{
+ return int(floor(x));
+}
+
+int quick_floor(float x)
+{
+ return int(x) - ((x < 0) ? 1 : 0);
+}
+
+#ifdef BIT_OPERATIONS
float integer_noise(int n)
{
int nn;
@@ -2373,24 +2419,18 @@ float integer_noise(int n)
return 0.5 * (float(nn) / 1073741824.0);
}
-int floor_to_int(float x)
-{
- return int(floor(x));
-}
-
-#ifdef BIT_OPERATIONS
uint hash(uint kx, uint ky, uint kz)
{
-#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
-#define final(a,b,c) \
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
+#define final(a, b, c) \
{ \
- c ^= b; c -= rot(b,14); \
- a ^= c; a -= rot(c,11); \
- b ^= a; b -= rot(a,25); \
- c ^= b; c -= rot(b,16); \
- a ^= c; a -= rot(c,4); \
- b ^= a; b -= rot(a,14); \
- c ^= b; c -= rot(b,24); \
+ c ^= b; c -= rot(b, 14); \
+ a ^= c; a -= rot(c, 11); \
+ b ^= a; b -= rot(a, 25); \
+ c ^= b; c -= rot(b, 16); \
+ a ^= c; a -= rot(c, 4); \
+ b ^= a; b -= rot(a, 14); \
+ c ^= b; c -= rot(b, 24); \
}
// now hash the data!
uint a, b, c, len = 3u;
@@ -2399,7 +2439,7 @@ uint hash(uint kx, uint ky, uint kz)
c += kz;
b += ky;
a += kx;
- final(a, b, c);
+ final (a, b, c);
return c;
#undef rot
@@ -2419,9 +2459,9 @@ float bits_to_01(uint bits)
float cellnoise(vec3 p)
{
- int ix = floor_to_int(p.x);
- int iy = floor_to_int(p.y);
- int iz = floor_to_int(p.z);
+ int ix = quick_floor(p.x);
+ int iy = quick_floor(p.y);
+ int iz = quick_floor(p.z);
return bits_to_01(hash(uint(ix), uint(iy), uint(iz)));
}
@@ -2459,10 +2499,10 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out vec4 result)
vec3 light_diffuse = gl_LightSource[i].diffuse.rgb;
float bsdf = max(dot(N, light_position), 0.0);
- L += light_diffuse*bsdf;
+ L += light_diffuse * bsdf;
}
- result = vec4(L*color.rgb, 1.0);
+ result = vec4(L * color.rgb, 1.0);
}
void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result)
@@ -2478,12 +2518,12 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, out vec4 result)
vec3 light_specular = gl_LightSource[i].specular.rgb;
/* we mix in some diffuse so low roughness still shows up */
- float bsdf = 0.5*pow(max(dot(N, H), 0.0), 1.0/roughness);
- bsdf += 0.5*max(dot(N, light_position), 0.0);
- L += light_specular*bsdf;
+ float bsdf = 0.5 * pow(max(dot(N, H), 0.0), 1.0 / roughness);
+ bsdf += 0.5 * max(dot(N, light_position), 0.0);
+ L += light_specular * bsdf;
}
- result = vec4(L*color.rgb, 1.0);
+ result = vec4(L * color.rgb, 1.0);
}
void node_bsdf_anisotropic(
@@ -2548,7 +2588,7 @@ void node_ambient_occlusion(vec4 color, out vec4 result)
void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
{
- result = color*strength;
+ result = color * strength;
}
/* background */
@@ -2564,7 +2604,7 @@ void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
void node_background(vec4 color, float strength, vec3 N, out vec4 result)
{
- result = color*strength;
+ result = color * strength;
}
/* closures */
@@ -2584,10 +2624,10 @@ void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader)
void node_fresnel(float ior, vec3 N, vec3 I, out float result)
{
/* handle perspective/orthographic */
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(I): vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
float eta = max(ior, 0.00001);
- result = fresnel_dielectric(I_view, N, (gl_FrontFacing)? eta: 1.0/eta);
+ result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta);
}
/* layer_weight */
@@ -2596,15 +2636,15 @@ void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float
{
/* fresnel */
float eta = max(1.0 - blend, 0.00001);
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(I): vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
- fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing)? 1.0/eta : eta );
+ fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta);
/* facing */
facing = abs(dot(I_view, N));
if (blend != 0.5) {
blend = clamp(blend, 0.0, 0.99999);
- blend = (blend < 0.5)? 2.0*blend: 0.5/(1.0 - blend);
+ blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend);
facing = pow(facing, blend);
}
facing = 1.0 - facing;
@@ -2628,12 +2668,9 @@ void node_gamma(vec4 col, float gamma, out vec4 outcol)
void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf)
{
- /* TODO(sergey): This needs linearization for vertex color.
- * But how to detect cases when input is linear and when it's srgb?
- */
outcol = vec4(attr, 1.0);
outvec = attr;
- outf = (attr.x + attr.y + attr.z)/3.0;
+ outf = (attr.x + attr.y + attr.z) / 3.0;
}
void node_uvmap(vec3 attr_uv, out vec3 outvec)
@@ -2641,48 +2678,51 @@ void node_uvmap(vec3 attr_uv, out vec3 outvec)
outvec = attr_uv;
}
-void node_geometry(vec3 I, vec3 N, mat4 toworld,
- out vec3 position, out vec3 normal, out vec3 tangent,
- out vec3 true_normal, out vec3 incoming, out vec3 parametric,
- out float backfacing, out float pointiness)
+void node_geometry(
+ vec3 I, vec3 N, mat4 toworld,
+ out vec3 position, out vec3 normal, out vec3 tangent,
+ out vec3 true_normal, out vec3 incoming, out vec3 parametric,
+ out float backfacing, out float pointiness)
{
- position = (toworld*vec4(I, 1.0)).xyz;
- normal = (toworld*vec4(N, 0.0)).xyz;
+ position = (toworld * vec4(I, 1.0)).xyz;
+ normal = (toworld * vec4(N, 0.0)).xyz;
tangent = vec3(0.0);
true_normal = normal;
/* handle perspective/orthographic */
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(I): vec3(0.0, 0.0, -1.0);
- incoming = -(toworld*vec4(I_view, 0.0)).xyz;
+ vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ incoming = -(toworld * vec4(I_view, 0.0)).xyz;
parametric = vec3(0.0);
- backfacing = (gl_FrontFacing)? 0.0: 1.0;
+ backfacing = (gl_FrontFacing) ? 0.0 : 1.0;
pointiness = 0.0;
}
-void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac,
- vec3 attr_orco, vec3 attr_uv,
- out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
- out vec3 camera, out vec3 window, out vec3 reflection)
+void node_tex_coord(
+ vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac,
+ vec3 attr_orco, vec3 attr_uv,
+ out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
+ out vec3 camera, out vec3 window, out vec3 reflection)
{
generated = attr_orco * 0.5 + vec3(0.5);
- normal = normalize((obinvmat*(viewinvmat*vec4(N, 0.0))).xyz);
+ normal = normalize((obinvmat * (viewinvmat * vec4(N, 0.0))).xyz);
uv = attr_uv;
- object = (obinvmat*(viewinvmat*vec4(I, 1.0))).xyz;
+ object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz;
camera = vec3(I.xy, -I.z);
vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0);
- window = vec3(mtex_2d_mapping(projvec.xyz/projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
+ window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
vec3 shade_I;
shade_view(I, shade_I);
vec3 view_reflection = reflect(shade_I, normalize(N));
- reflection = (viewinvmat*vec4(view_reflection, 0.0)).xyz;
+ reflection = (viewinvmat * vec4(view_reflection, 0.0)).xyz;
}
-void node_tex_coord_background(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac,
- vec3 attr_orco, vec3 attr_uv,
- out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
- out vec3 camera, out vec3 window, out vec3 reflection)
+void node_tex_coord_background(
+ vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac,
+ vec3 attr_orco, vec3 attr_uv,
+ out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
+ out vec3 camera, out vec3 window, out vec3 reflection)
{
vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
@@ -2698,9 +2738,9 @@ void node_tex_coord_background(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, v
object = coords;
camera = vec3(co.xy, -co.z);
- window = (gl_ProjectionMatrix[3][3] == 0.0) ?
- vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) :
- vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0);
+ window = (gl_ProjectionMatrix[3][3] == 0.0) ?
+ vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) :
+ vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0);
reflection = -coords;
}
@@ -2718,12 +2758,12 @@ float calc_gradient(vec3 p, int gradient_type)
}
else if (gradient_type == 1) { /* quadratic */
float r = max(x, 0.0);
- return r*r;
+ return r * r;
}
else if (gradient_type == 2) { /* easing */
float r = min(max(x, 0.0), 1.0);
- float t = r*r;
- return (3.0*t - 2.0*t*r);
+ float t = r * r;
+ return (3.0 * t - 2.0 * t * r);
}
else if (gradient_type == 3) { /* diagonal */
return (x + y) * 0.5;
@@ -2732,9 +2772,9 @@ float calc_gradient(vec3 p, int gradient_type)
return atan(y, x) / (M_PI * 2) + 0.5;
}
else {
- float r = max(1.0 - sqrt(x*x + y*y + z*z), 0.0);
+ float r = max(1.0 - sqrt(x * x + y * y + z * z), 0.0);
if (gradient_type == 5) { /* quadratic sphere */
- return r*r;
+ return r * r;
}
else if (gradient_type == 6) { /* sphere */
return r;
@@ -2757,20 +2797,21 @@ void node_tex_checker(vec3 co, vec4 color1, vec4 color2, float scale, out vec4 c
vec3 p = co * scale;
/* Prevent precision issues on unit coordinates. */
- p.x = (p.x + 0.000001)*0.999999;
- p.y = (p.y + 0.000001)*0.999999;
- p.z = (p.z + 0.000001)*0.999999;
+ p.x = (p.x + 0.000001) * 0.999999;
+ p.y = (p.y + 0.000001) * 0.999999;
+ p.z = (p.z + 0.000001) * 0.999999;
- int xi = abs(int(floor(p.x)));
- int yi = abs(int(floor(p.y)));
- int zi = abs(int(floor(p.z)));
+ int xi = int(abs(floor(p.x)));
+ int yi = int(abs(floor(p.y)));
+ int zi = int(abs(floor(p.z)));
- bool check = ((xi % 2 == yi % 2) == bool(zi % 2));
+ bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2)));
color = check ? color1 : color2;
fac = check ? 1.0 : 0.0;
}
+#ifdef BIT_OPERATIONS
vec2 calc_brick_texture(vec3 p, float mortar_size, float bias,
float brick_width, float row_height,
float offset_amount, int offset_frequency,
@@ -2784,19 +2825,20 @@ vec2 calc_brick_texture(vec3 p, float mortar_size, float bias,
if (offset_frequency != 0 && squash_frequency != 0) {
brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */
- offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width*offset_amount); /* offset */
+ offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */
}
- bricknum = floor_to_int((p.x+offset) / brick_width);
+ bricknum = floor_to_int((p.x + offset) / brick_width);
- x = (p.x+offset) - brick_width*bricknum;
- y = p.y - row_height*rownum;
+ x = (p.x + offset) - brick_width * bricknum;
+ y = p.y - row_height * rownum;
return vec2(clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0),
(x < mortar_size || y < mortar_size ||
x > (brick_width - mortar_size) ||
y > (row_height - mortar_size)) ? 1.0 : 0.0);
}
+#endif
void node_tex_brick(vec3 co,
vec4 color1, vec4 color2,
@@ -2807,7 +2849,8 @@ void node_tex_brick(vec3 co,
float squash_amount, float squash_frequency,
out vec4 color, out float fac)
{
- vec2 f2 = calc_brick_texture(co*scale,
+#ifdef BIT_OPERATIONS
+ vec2 f2 = calc_brick_texture(co * scale,
mortar_size, bias,
brick_width, row_height,
offset_amount, int(offset_frequency),
@@ -2820,6 +2863,10 @@ void node_tex_brick(vec3 co,
}
color = (f == 1.0) ? mortar : color1;
fac = f;
+#else
+ color = vec4(1.0);
+ fac = 1.0;
+#endif
}
void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac)
@@ -2831,8 +2878,8 @@ void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac)
void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color)
{
vec3 nco = normalize(co);
- float u = -atan(nco.y, nco.x)/(2.0*M_PI) + 0.5;
- float v = atan(nco.z, hypot(nco.x, nco.y))/M_PI + 0.5;
+ float u = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5;
+ float v = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5;
color = texture2D(ima, vec2(u, v));
}
@@ -2843,12 +2890,12 @@ void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color)
nco.y -= 1.0;
- float div = 2.0*sqrt(max(-0.5*nco.y, 0.0));
+ float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0));
if (div > 0.0)
nco /= div;
- float u = 0.5*(nco.x + 1.0);
- float v = 0.5*(nco.z + 1.0);
+ float u = 0.5 * (nco.x + 1.0);
+ float v = 0.5 * (nco.z + 1.0);
color = texture2D(ima, vec2(u, v));
}
@@ -2864,6 +2911,82 @@ void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha)
alpha = color.a;
}
+void node_tex_image_box(vec3 texco,
+ vec3 nob,
+ sampler2D ima,
+ float blend,
+ out vec4 color,
+ out float alpha)
+{
+ /* project from direction vector to barycentric coordinates in triangles */
+ nob = vec3(abs(nob.x), abs(nob.y), abs(nob.z));
+ nob /= (nob.x + nob.y + nob.z);
+
+ /* basic idea is to think of this as a triangle, each corner representing
+ * one of the 3 faces of the cube. in the corners we have single textures,
+ * in between we blend between two textures, and in the middle we a blend
+ * between three textures.
+ *
+ * the Nxyz values are the barycentric coordinates in an equilateral
+ * triangle, which in case of blending, in the middle has a smaller
+ * equilateral triangle where 3 textures blend. this divides things into
+ * 7 zones, with an if () test for each zone */
+
+ vec3 weight = vec3(0.0, 0.0, 0.0);
+ float limit = 0.5 * (1.0 + blend);
+
+ /* first test for corners with single texture */
+ if (nob.x > limit * (nob.x + nob.y) && nob.x > limit * (nob.x + nob.z)) {
+ weight.x = 1.0;
+ }
+ else if (nob.y > limit * (nob.x + nob.y) && nob.y > limit * (nob.y + nob.z)) {
+ weight.y = 1.0;
+ }
+ else if (nob.z > limit * (nob.x + nob.z) && nob.z > limit * (nob.y + nob.z)) {
+ weight.z = 1.0;
+ }
+ else if (blend > 0.0) {
+ /* in case of blending, test for mixes between two textures */
+ if (nob.z < (1.0 - limit) * (nob.y + nob.x)) {
+ weight.x = nob.x / (nob.x + nob.y);
+ weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
+ weight.y = 1.0 - weight.x;
+ }
+ else if (nob.x < (1.0 - limit) * (nob.y + nob.z)) {
+ weight.y = nob.y / (nob.y + nob.z);
+ weight.y = clamp((weight.y - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
+ weight.z = 1.0 - weight.y;
+ }
+ else if (nob.y < (1.0 - limit) * (nob.x + nob.z)) {
+ weight.x = nob.x / (nob.x + nob.z);
+ weight.x = clamp((weight.x - 0.5 * (1.0 - blend)) / blend, 0.0, 1.0);
+ weight.z = 1.0 - weight.x;
+ }
+ else {
+ /* last case, we have a mix between three */
+ weight.x = ((2.0 - limit) * nob.x + (limit - 1.0)) / (2.0 * limit - 1.0);
+ weight.y = ((2.0 - limit) * nob.y + (limit - 1.0)) / (2.0 * limit - 1.0);
+ weight.z = ((2.0 - limit) * nob.z + (limit - 1.0)) / (2.0 * limit - 1.0);
+ }
+ }
+ else {
+ /* Desperate mode, no valid choice anyway, fallback to one side.*/
+ weight.x = 1.0;
+ }
+ color = vec4(0);
+ if (weight.x > 0.0) {
+ color += weight.x * texture2D(ima, texco.yz);
+ }
+ if (weight.y > 0.0) {
+ color += weight.y * texture2D(ima, texco.xz);
+ }
+ if (weight.z > 0.0) {
+ color += weight.z * texture2D(ima, texco.yx);
+ }
+
+ alpha = color.a;
+}
+
void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
{
color = vec4(0.0);
@@ -2873,42 +2996,42 @@ void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
void node_tex_magic(vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac)
{
vec3 p = co * scale;
- float x = sin((p.x + p.y + p.z)*5.0);
- float y = cos((-p.x + p.y - p.z)*5.0);
- float z = -cos((-p.x - p.y + p.z)*5.0);
+ float x = sin((p.x + p.y + p.z) * 5.0);
+ float y = cos((-p.x + p.y - p.z) * 5.0);
+ float z = -cos((-p.x - p.y + p.z) * 5.0);
if (depth > 0) {
x *= distortion;
y *= distortion;
z *= distortion;
- y = -cos(x-y+z);
+ y = -cos(x - y + z);
y *= distortion;
if (depth > 1) {
- x = cos(x-y-z);
+ x = cos(x - y - z);
x *= distortion;
if (depth > 2) {
- z = sin(-x-y-z);
+ z = sin(-x - y - z);
z *= distortion;
if (depth > 3) {
- x = -cos(-x+y-z);
+ x = -cos(-x + y - z);
x *= distortion;
if (depth > 4) {
- y = -sin(-x+y+z);
+ y = -sin(-x + y + z);
y *= distortion;
if (depth > 5) {
- y = -cos(-x+y+z);
+ y = -cos(-x + y + z);
y *= distortion;
if (depth > 6) {
- x = cos(x+y+z);
+ x = cos(x + y + z);
x *= distortion;
if (depth > 7) {
- z = sin(x+y-z);
+ z = sin(x + y - z);
z *= distortion;
if (depth > 8) {
- x = -cos(-x-y+z);
+ x = -cos(-x - y + z);
x *= distortion;
if (depth > 9) {
- y = -sin(x-y+z);
+ y = -sin(x - y + z);
y *= distortion;
}
}
@@ -2927,7 +3050,7 @@ void node_tex_magic(vec3 co, float scale, float distortion, float depth, out vec
z /= distortion;
}
- color = vec4(0.5 - x, 0.5 - y, 0.f - z, 1.0);
+ color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0);
fac = (color.x + color.y + color.z) / 3.0;
}
@@ -2968,14 +3091,14 @@ float noise_perlin(float x, float y, float z)
float result;
- result = noise_nerp(w, noise_nerp(v, noise_nerp(u, noise_grad(hash(X, Y, Z), fx, fy, fz ),
- noise_grad(hash(X+1, Y, Z), fx-1.0, fy, fz)),
- noise_nerp(u, noise_grad(hash(X, Y+1, Z), fx, fy - 1.0, fz),
- noise_grad(hash(X+1, Y+1, Z), fx-1.0, fy-1.0, fz))),
- noise_nerp(v, noise_nerp(u, noise_grad(hash(X, Y, Z+1), fx, fy, fz-1.0),
- noise_grad(hash(X+1, Y, Z+1), fx-1.0, fy, fz-1.0)),
- noise_nerp(u, noise_grad(hash(X, Y+1, Z+1), fx, fy-1.0, fz-1.0),
- noise_grad(hash(X+1, Y+1, Z+1), fx-1.0, fy-1.0, fz-1.0))));
+ result = noise_nerp(w, noise_nerp(v, noise_nerp(u, noise_grad(hash(X, Y, Z), fx, fy, fz),
+ noise_grad(hash(X + 1, Y, Z), fx - 1.0, fy, fz)),
+ noise_nerp(u, noise_grad(hash(X, Y + 1, Z), fx, fy - 1.0, fz),
+ noise_grad(hash(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz))),
+ noise_nerp(v, noise_nerp(u, noise_grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0),
+ noise_grad(hash(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0)),
+ noise_nerp(u, noise_grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0),
+ noise_grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0))));
return noise_scale3(result);
}
@@ -2998,27 +3121,27 @@ float noise_turbulence(vec3 p, float octaves, int hard)
octaves = clamp(octaves, 0.0, 16.0);
n = int(octaves);
for (i = 0; i <= n; i++) {
- float t = noise(fscale*p);
+ float t = noise(fscale * p);
if (hard != 0) {
- t = abs(2.0*t - 1.0);
+ t = abs(2.0 * t - 1.0);
}
- sum += t*amp;
+ sum += t * amp;
amp *= 0.5;
fscale *= 2.0;
}
float rmd = octaves - floor(octaves);
if (rmd != 0.0) {
- float t = noise(fscale*p);
+ float t = noise(fscale * p);
if (hard != 0) {
- t = abs(2.0*t - 1.0);
+ t = abs(2.0 * t - 1.0);
}
- float sum2 = sum + t*amp;
- sum *= (float(1 << n) / float((1 << (n+1)) - 1));
- sum2 *= (float(1 << (n+1)) / float((1 << (n+2)) - 1));
- return (1.0 - rmd)*sum + rmd*sum2;
+ float sum2 = sum + t * amp;
+ sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
+ sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
+ return (1.0 - rmd) * sum + rmd * sum2;
}
else {
- sum *= (float(1 << n) / float((1 << (n+1)) - 1));
+ sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
return sum;
}
}
@@ -3224,15 +3347,15 @@ float svm_musgrave(int type,
vec3 p)
{
if (type == 0 /*NODE_MUSGRAVE_MULTIFRACTAL*/)
- return intensity*noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
+ return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
else if (type == 1 /*NODE_MUSGRAVE_FBM*/)
- return intensity*noise_musgrave_fBm(p, dimension, lacunarity, octaves);
+ return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
else if (type == 2 /*NODE_MUSGRAVE_HYBRID_MULTIFRACTAL*/)
- return intensity*noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
+ return intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
else if (type == 3 /*NODE_MUSGRAVE_RIDGED_MULTIFRACTAL*/)
- return intensity*noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
+ return intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
else if (type == 4 /*NODE_MUSGRAVE_HETERO_TERRAIN*/)
- return intensity*noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
+ return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
return 0.0;
}
#endif // #ifdef BIT_OPERATIONS
@@ -3256,7 +3379,7 @@ void node_tex_musgrave(vec3 co,
offset,
1.0,
gain,
- co*scale);
+ co * scale);
#else
fac = 1.0;
#endif
@@ -3353,7 +3476,7 @@ float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int
n = length(p) * 20.0;
if (distortion != 0.0)
- n += distortion * noise_turbulence(p*detail_scale, detail, 0);
+ n += distortion * noise_turbulence(p * detail_scale, detail, 0);
if (wave_profile == 0) { /* profile sin */
return 0.5 + 0.5 * sin(n);
@@ -3361,7 +3484,7 @@ float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int
else { /* profile saw */
n /= 2.0 * M_PI;
n -= int(n);
- return (n < 0.0)? n + 1.0: n;
+ return (n < 0.0) ? n + 1.0 : n;
}
}
#endif // BIT_OPERATIONS
@@ -3372,7 +3495,7 @@ void node_tex_wave(
{
#ifdef BIT_OPERATIONS
float f;
- f = calc_wave(co*scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile));
+ f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile));
color = vec4(f, f, f, 1.0);
fac = f;
@@ -3451,12 +3574,12 @@ void node_bump(float strength, float dist, float height, vec3 N, vec3 surf_pos,
float dHdx = dFdx(height);
float dHdy = dFdy(height);
- vec3 surfgrad = dHdx*Rx + dHdy*Ry;
+ vec3 surfgrad = dHdx * Rx + dHdy * Ry;
strength = max(strength, 0.0);
- result = normalize(absdet*N - dist*sign(det)*surfgrad);
- result = normalize(strength*result + (1.0 - strength)*N);
+ result = normalize(absdet * N - dist * sign(det) * surfgrad);
+ result = normalize(strength * result + (1.0 - strength) * N);
}
/* output */
@@ -3479,7 +3602,7 @@ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out v
vec2 tex;
#ifndef USE_OPENSUBDIV
- /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
+ /* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
* between shader stages and we want the full range of the normal */
normal = vec3(2.0, 2.0, 2.0) * vec3(N.x, N.y, N.z) - vec3(1.0, 1.0, 1.0);
if (normal.z < 0.0) {
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
index 5f406c959f1..b485d2cce86 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
@@ -4,13 +4,13 @@ uniform sampler2D textureSource;
void main()
{
vec4 color = vec4(0.0);
- color += texture2D( textureSource, gl_TexCoord[0].st + vec2(-3.0 * ScaleU.x, -3.0 * ScaleU.y ) ) * 0.015625;
- color += texture2D( textureSource, gl_TexCoord[0].st + vec2(-2.0 * ScaleU.x, -2.0 * ScaleU.y ) ) * 0.09375;
- color += texture2D( textureSource, gl_TexCoord[0].st + vec2(-1.0 * ScaleU.x, -1.0 * ScaleU.y ) ) * 0.234375;
- color += texture2D( textureSource, gl_TexCoord[0].st + vec2(0.0, 0.0)) * 0.3125;
- color += texture2D( textureSource, gl_TexCoord[0].st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y ) ) * 0.234375;
- color += texture2D( textureSource, gl_TexCoord[0].st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y ) ) * 0.09375;
- color += texture2D( textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y ) ) * 0.015625;
+ color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-3.0 * ScaleU.x, -3.0 * ScaleU.y)) * 0.015625;
+ color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-2.0 * ScaleU.x, -2.0 * ScaleU.y)) * 0.09375;
+ color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-1.0 * ScaleU.x, -1.0 * ScaleU.y)) * 0.234375;
+ color += texture2D(textureSource, gl_TexCoord[0].st + vec2(0.0, 0.0)) * 0.3125;
+ color += texture2D(textureSource, gl_TexCoord[0].st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y)) * 0.234375;
+ color += texture2D(textureSource, gl_TexCoord[0].st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y)) * 0.09375;
+ color += texture2D(textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y)) * 0.015625;
gl_FragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
index 9bb2e7ad469..5d00108b052 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -1,6 +1,6 @@
void main()
{
- gl_Position = ftransform();
- gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_Position = ftransform();
+ gl_TexCoord[0] = gl_MultiTexCoord0;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
index 5824d5a80db..9a6537b4f09 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
@@ -14,6 +14,68 @@ varying vec3 varnormal;
varying float gl_ClipDistance[6];
#endif
+float srgb_to_linearrgb(float c)
+{
+ if (c < 0.04045)
+ return (c < 0.0) ? 0.0 : c * (1.0 / 12.92);
+ else
+ return pow((c + 0.055) * (1.0 / 1.055), 2.4);
+}
+
+void srgb_to_linearrgb(vec3 col_from, out vec3 col_to)
+{
+ col_to.r = srgb_to_linearrgb(col_from.r);
+ col_to.g = srgb_to_linearrgb(col_from.g);
+ col_to.b = srgb_to_linearrgb(col_from.b);
+}
+
+void srgb_to_linearrgb(vec4 col_from, out vec4 col_to)
+{
+ col_to.r = srgb_to_linearrgb(col_from.r);
+ col_to.g = srgb_to_linearrgb(col_from.g);
+ col_to.b = srgb_to_linearrgb(col_from.b);
+ col_to.a = col_from.a;
+}
+
+bool is_srgb(int info)
+{
+#ifdef USE_NEW_SHADING
+ return (info == 1)? true: false;
+#else
+ return false;
+#endif
+}
+
+void set_var_from_attr(float attr, int info, out float var)
+{
+ var = attr;
+}
+
+void set_var_from_attr(vec2 attr, int info, out vec2 var)
+{
+ var = attr;
+}
+
+void set_var_from_attr(vec3 attr, int info, out vec3 var)
+{
+ if (is_srgb(info)) {
+ srgb_to_linearrgb(attr, var);
+ }
+ else {
+ var = attr;
+ }
+}
+
+void set_var_from_attr(vec4 attr, int info, out vec4 var)
+{
+ if (is_srgb(info)) {
+ srgb_to_linearrgb(attr, var);
+ }
+ else {
+ var = attr;
+ }
+}
+
void main()
{
#ifndef USE_OPENSUBDIV
diff --git a/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl b/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
index 4838289ff9e..3761bf350eb 100644
--- a/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
@@ -15,7 +15,7 @@ void main()
// Adjusting moments using partial derivative
float dx = dFdx(depth);
float dy = dFdy(depth);
- moment2 += 0.25*(dx*dx+dy*dy);
+ moment2 += 0.25 * (dx * dx + dy * dy);
gl_FragColor = vec4(moment1, moment2, 0.0, 0.0);
}
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index f4763883489..d89393b9903 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -83,18 +83,10 @@
# include <libswscale/swscale.h>
#endif
-/* actually hard coded endianness */
-#define GET_BIG_LONG(x) (((uchar *) (x))[0] << 24 | ((uchar *) (x))[1] << 16 | ((uchar *) (x))[2] << 8 | ((uchar *) (x))[3])
-#define GET_LITTLE_LONG(x) (((uchar *) (x))[3] << 24 | ((uchar *) (x))[2] << 16 | ((uchar *) (x))[1] << 8 | ((uchar *) (x))[0])
-#define SWAP_L(x) (((x << 24) & 0xff000000) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | ((x >> 24) & 0xff))
-#define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff))
-
/* more endianness... should move to a separate file... */
#ifdef __BIG_ENDIAN__
-# define GET_ID GET_BIG_LONG
# define LITTLE_LONG SWAP_LONG
#else
-# define GET_ID GET_LITTLE_LONG
# define LITTLE_LONG ENDIAN_NOP
#endif
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 321ff26f68f..5b533d1ec48 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -298,7 +298,7 @@ typedef struct View3D {
#define RV3D_VIEW_CAMERA 8
#define RV3D_VIEW_IS_AXIS(view) \
- ((view >= RV3D_VIEW_FRONT) && (view <= RV3D_VIEW_BOTTOM))
+ (((view) >= RV3D_VIEW_FRONT) && ((view) <= RV3D_VIEW_BOTTOM))
/* View3d->flag2 (short) */
#define V3D_RENDER_OVERRIDE (1 << 2)
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 09f4ea1cf02..f623416f673 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -955,6 +955,7 @@ bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, struct ListBas
char *RNA_path_from_ID_to_struct(PointerRNA *ptr);
char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop);
+char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, PropertyRNA *prop, int array_dim, int index);
char *RNA_path_resolve_from_type_to_property(
struct PointerRNA *ptr, struct PropertyRNA *prop,
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 97c71715349..c49a6197a4e 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -4642,7 +4642,47 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr)
return ptrpath;
}
-char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
+static void rna_path_array_multi_from_flat_index(
+ const int dimsize[RNA_MAX_ARRAY_LENGTH], const int totdims,
+ const int index_dim, int index,
+ int r_index_multi[RNA_MAX_ARRAY_LENGTH])
+{
+ int dimsize_step[RNA_MAX_ARRAY_LENGTH + 1];
+ int i = totdims - 1;
+ dimsize_step[i + 1] = 1;
+ dimsize_step[i] = dimsize[i];
+ while (--i != -1) {
+ dimsize_step[i] = dimsize[i] * dimsize_step[i + 1];
+ }
+ while (++i != index_dim) {
+ int index_round = index / dimsize_step[i + 1];
+ r_index_multi[i] = index_round;
+ index -= (index_round * dimsize_step[i + 1]);
+ }
+ BLI_assert(index == 0);
+}
+
+static void rna_path_array_multi_string_from_flat_index(
+ PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index,
+ char *index_str, int index_str_len)
+{
+ int dimsize[RNA_MAX_ARRAY_LENGTH];
+ int totdims = RNA_property_array_dimension(ptr, prop, dimsize);
+ int index_multi[RNA_MAX_ARRAY_LENGTH];
+
+ rna_path_array_multi_from_flat_index(dimsize, totdims, index_dim, index, index_multi);
+
+ for (int i = 0, offset = 0; (i < index_dim) && (offset < index_str_len); i++) {
+ offset += BLI_snprintf_rlen(&index_str[offset], index_str_len - offset, "[%d]", index_multi[i]);
+ }
+}
+
+/**
+ * \param index_dim: The dimensiuon to show, 0 disables. 1 for 1d array, 2 for 2d. etc.
+ * \param index: The *flattened* index to use when \a ``index_dim > 0``,
+ * this is expanded when used with multi-dimensional arrays.
+ */
+char *RNA_path_from_ID_to_property_index(PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index)
{
const bool is_rna = (prop->magic == RNA_MAGIC);
const char *propname;
@@ -4656,25 +4696,36 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
propname = RNA_property_identifier(prop);
+ /* support indexing w/ multi-dimensional arrays */
+ char index_str[RNA_MAX_ARRAY_LENGTH * 12 + 1];
+ if (index_dim == 0) {
+ index_str[0] = '\0';
+ }
+ else {
+ rna_path_array_multi_string_from_flat_index(
+ ptr, prop, index_dim, index,
+ index_str, sizeof(index_str));
+ }
+
if (ptrpath) {
if (is_rna) {
- path = BLI_sprintfN("%s.%s", ptrpath, propname);
+ path = BLI_sprintfN("%s.%s%s", ptrpath, propname, index_str);
}
else {
char propname_esc[MAX_IDPROP_NAME * 2];
BLI_strescape(propname_esc, propname, sizeof(propname_esc));
- path = BLI_sprintfN("%s[\"%s\"]", ptrpath, propname_esc);
+ path = BLI_sprintfN("%s[\"%s\"]%s", ptrpath, propname_esc, index_str);
}
MEM_freeN(ptrpath);
}
else if (RNA_struct_is_ID(ptr->type)) {
if (is_rna) {
- path = BLI_strdup(propname);
+ path = BLI_sprintfN("%s%s", propname, index_str);
}
else {
char propname_esc[MAX_IDPROP_NAME * 2];
BLI_strescape(propname_esc, propname, sizeof(propname_esc));
- path = BLI_sprintfN("[\"%s\"]", propname_esc);
+ path = BLI_sprintfN("[\"%s\"]%s", propname_esc, index_str);
}
}
else {
@@ -4684,6 +4735,11 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
return path;
}
+char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
+{
+ return RNA_path_from_ID_to_property_index(ptr, prop, 0, -1);
+}
+
/**
* \return the path to given ptr/prop from the closest ancestor of given type, if any (else return NULL).
*/
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index dcb4d65f3f9..678b0ac8f1f 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -131,8 +131,8 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
prop = RNA_def_property(srna, "interocular_distance", PROP_FLOAT, PROP_DISTANCE);
- RNA_def_property_range(prop, 0.0f, 100.0f);
- RNA_def_property_ui_range(prop, 0.0f, 1.f, 1, 3);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 1e4f, 1, 3);
RNA_def_property_ui_text(prop, "Interocular Distance",
"Set the distance between the eyes - the stereo plane distance / 30 should be fine");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index d28dd8f7607..cb7a40a9238 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -1009,13 +1009,15 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna)
prop = RNA_def_property(srna, "offset_x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "xof");
- RNA_def_property_range(prop, -50.0f, 50.0f);
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, -50.0f, 50.0f, 10, 3);
RNA_def_property_ui_text(prop, "X Offset", "Horizontal offset from the object origin");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "offset_y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "yof");
- RNA_def_property_range(prop, -50.0f, 50.0f);
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, -50.0f, 50.0f, 10, 3);
RNA_def_property_ui_text(prop, "Y Offset", "Vertical offset from the object origin");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
@@ -1117,25 +1119,29 @@ static void rna_def_textbox(BlenderRNA *brna)
/* number values */
prop = RNA_def_property(srna, "x", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "x");
- RNA_def_property_range(prop, -50.0f, 50.0f);
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, -50.0f, 50.0f, 10, 3);
RNA_def_property_ui_text(prop, "Textbox X Offset", "");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "y", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "y");
- RNA_def_property_range(prop, -50.0f, 50.0f);
+ RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+ RNA_def_property_ui_range(prop, -50.0f, 50.0f, 10, 3);
RNA_def_property_ui_text(prop, "Textbox Y Offset", "");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "width", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "w");
- RNA_def_property_range(prop, 0.0f, 50.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 50.0f, 10, 3);
RNA_def_property_ui_text(prop, "Textbox Width", "");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "height", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "h");
- RNA_def_property_range(prop, 0.0f, 50.0f);
+ RNA_def_property_range(prop, 0.0f, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0f, 50.0f, 10, 3);
RNA_def_property_ui_text(prop, "Textbox Height", "");
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index bd14f206665..dffdd7fe6c7 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -802,6 +802,7 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree, ReportList *reports,
ntreeUpdateTree(G.main, ntree);
+ ED_node_tag_update_nodetree(G.main, ntree, ret->tonode);
WM_main_add_notifier(NC_NODE | NA_EDITED, ntree);
}
return ret;
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 26cfc396cca..84360ba4386 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -649,7 +649,7 @@ void RNA_api_object(StructRNA *srna)
#endif /* NDEBUG */
func = RNA_def_function(srna, "update_from_editmode", "rna_Object_update_from_editmode");
- RNA_def_function_ui_description(func, "Load the objects edit-mode data intp the object data");
+ RNA_def_function_ui_description(func, "Load the objects edit-mode data into the object data");
parm = RNA_def_boolean(func, "result", 0, "", "Success");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 74fb4a08eda..e1216e3c85f 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -196,6 +196,7 @@ static void rna_Scene_collada_export(
int use_ngons,
int use_object_instantiation,
+ int use_blender_profile,
int sort_by_name,
int export_transformation_type,
int open_sim)
@@ -203,7 +204,7 @@ static void rna_Scene_collada_export(
collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected,
include_children, include_armatures, include_shapekeys, deform_bones_only,
active_uv_only, include_uv_textures, include_material_textures,
- use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, export_transformation_type, open_sim);
+ use_texture_copies, use_ngons, use_object_instantiation, use_blender_profile, sort_by_name, export_transformation_type, open_sim);
}
#endif
@@ -286,6 +287,7 @@ void RNA_api_scene(StructRNA *srna)
parm = RNA_def_boolean(func, "use_ngons", 1, "Use NGons", "Keep NGons in Export");
parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data");
+ parm = RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile", "Export additional Blender specific information (for material, shaders, bones, etc.)");
parm = RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name");
parm = RNA_def_boolean(func, "open_sim", 0, "Export for SL/OpenSim", "Compatibility mode for SL, OpenSim and similar online worlds");
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 68d4f7f7e51..c3a66058888 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -2327,6 +2327,7 @@ static void rna_def_text(StructRNA *srna)
prop = RNA_def_property(srna, "font_size", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "text_size");
RNA_def_property_ui_text(prop, "Size", "Size of the text");
+ RNA_def_property_range(prop, 0.0, 2000);
RNA_def_property_ui_range(prop, 0.0f, 1000, 1, -1);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index 41ebd865720..df94975e274 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -73,7 +73,7 @@ typedef struct ScrewVertIter {
#define SV_UNUSED (UINT_MAX)
#define SV_INVALID ((UINT_MAX) - 1)
-#define SV_IS_VALID(v) (v < SV_INVALID)
+#define SV_IS_VALID(v) ((v) < SV_INVALID)
static void screwvert_iter_init(ScrewVertIter *iter, ScrewVertConnect *array, unsigned int v_init, unsigned int dir)
{
diff --git a/source/blender/nodes/shader/nodes/node_shader_camera.c b/source/blender/nodes/shader/nodes/node_shader_camera.c
index 49ebb15d7a4..3bdb5c36d69 100644
--- a/source/blender/nodes/shader/nodes/node_shader_camera.c
+++ b/source/blender/nodes/shader/nodes/node_shader_camera.c
@@ -54,7 +54,15 @@ static void node_shader_exec_camera(void *data, int UNUSED(thread), bNode *UNUSE
static int gpu_shader_camera(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, "camera", in, out, GPU_builtin(GPU_VIEW_POSITION));
+ GPUNodeLink *viewvec;
+
+ viewvec = GPU_builtin(GPU_VIEW_POSITION);
+
+ /* Blender has negative Z, Cycles positive Z convention */
+ if (GPU_material_use_new_shading_nodes(mat))
+ GPU_link(mat, "invert_z", viewvec, &viewvec);
+
+ return GPU_stack_link(mat, "camera", in, out, viewvec);
}
void register_node_type_sh_camera(void)
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
index d2695609a88..85e2c77662d 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -133,29 +133,33 @@ static int gpu_shader_normal_map(GPUMaterial *mat, bNode *node, bNodeExecData *U
/* **************** CYCLES ******************** */
- GPU_link(mat, "direction_transform_m4v3", negnorm, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &negnorm);
-
switch (nm->space) {
case SHD_NORMAL_MAP_TANGENT:
GPU_link(mat, "color_to_normal_new_shading", realnorm, &realnorm);
GPU_link(mat, "node_normal_map", GPU_attribute(CD_TANGENT, nm->uv_map), negnorm, realnorm, &realnorm);
- break;
+ GPU_link(mat, "vec_math_mix", strength, realnorm, GPU_builtin(GPU_VIEW_NORMAL), &out[0].link);
+ /* for uniform scale this is sufficient to match Cycles */
+ GPU_link(mat, "direction_transform_m4v3", out[0].link, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &out[0].link);
+ GPU_link(mat, "vect_normalize", out[0].link, &out[0].link);
+ return true;
case SHD_NORMAL_MAP_OBJECT:
+ GPU_link(mat, "direction_transform_m4v3", negnorm, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &negnorm);
GPU_link(mat, "color_to_normal_new_shading", realnorm, &realnorm);
GPU_link(mat, "direction_transform_m4v3", realnorm, GPU_builtin(GPU_OBJECT_MATRIX), &realnorm);
break;
case SHD_NORMAL_MAP_BLENDER_OBJECT:
+ GPU_link(mat, "direction_transform_m4v3", negnorm, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &negnorm);
GPU_link(mat, "color_to_blender_normal_new_shading", realnorm, &realnorm);
GPU_link(mat, "direction_transform_m4v3", realnorm, GPU_builtin(GPU_OBJECT_MATRIX), &realnorm);
break;
case SHD_NORMAL_MAP_WORLD:
+ GPU_link(mat, "direction_transform_m4v3", negnorm, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &negnorm);
GPU_link(mat, "color_to_normal_new_shading", realnorm, &realnorm);
break;
case SHD_NORMAL_MAP_BLENDER_WORLD:
+ GPU_link(mat, "direction_transform_m4v3", negnorm, GPU_builtin(GPU_INVERSE_VIEW_MATRIX), &negnorm);
GPU_link(mat, "color_to_blender_normal_new_shading", realnorm, &realnorm);
break;
-
- GPU_link(mat, "vect_normalize", realnorm, &realnorm);
}
} else {
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index f0a8cda045e..71200dfe9d3 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -59,17 +59,49 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
Image *ima = (Image *)node->id;
ImageUser *iuser = NULL;
NodeTexImage *tex = node->storage;
+
+ GPUNodeLink *norm;
+
int isdata = tex->color_space == SHD_COLORSPACE_NONE;
+ float blend = tex->projection_blend;
if (!ima)
return GPU_stack_link(mat, "node_tex_image_empty", in, out);
-
+
if (!in[0].link)
in[0].link = GPU_attribute(CD_MTFACE, "");
node_shader_gpu_tex_mapping(mat, node, in, out);
- GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ switch (tex->projection) {
+ case SHD_PROJ_FLAT:
+ GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ break;
+ case SHD_PROJ_BOX:
+ GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL),
+ GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
+ &norm);
+ GPU_link(mat, "direction_transform_m4v3", norm,
+ GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
+ &norm);
+ GPU_link(mat, "node_tex_image_box", in[0].link,
+ norm,
+ GPU_image(ima, iuser, isdata),
+ GPU_uniform(&blend),
+ &out[0].link,
+ &out[1].link);
+ break;
+ case SHD_PROJ_SPHERE:
+ GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
+ GPU_link(mat, "point_map_to_sphere", in[0].link, &in[0].link);
+ GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ break;
+ case SHD_PROJ_TUBE:
+ GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
+ GPU_link(mat, "point_map_to_tube", in[0].link, &in[0].link);
+ GPU_stack_link(mat, "node_tex_image", in, out, GPU_image(ima, iuser, isdata));
+ break;
+ }
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
if ((tex->color_space == SHD_COLORSPACE_COLOR) &&
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 33ac58dadb1..49b806347d6 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -973,7 +973,9 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self)
RNA_property_identifier(self->prop));
}
-static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self)
+static PyObject *pyrna_prop_repr_ex(
+ BPy_PropertyRNA *self,
+ const int index_dim, const int index)
{
ID *id = self->ptr.id.data;
PyObject *tmp_str;
@@ -987,7 +989,8 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self)
tmp_str = PyUnicode_FromString(id->name + 2);
- path = RNA_path_from_ID_to_property(&self->ptr, self->prop);
+ path = RNA_path_from_ID_to_property_index(&self->ptr, self->prop, index_dim, index);
+
if (path) {
const char *data_delim = (path[0] == '[') ? "" : ".";
if (GS(id->name) == ID_NT) { /* nodetree paths are not accurate */
@@ -1015,6 +1018,15 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self)
return ret;
}
+static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self)
+{
+ return pyrna_prop_repr_ex(self, 0, -1);
+}
+
+static PyObject *pyrna_prop_array_repr(BPy_PropertyArrayRNA *self)
+{
+ return pyrna_prop_repr_ex((BPy_PropertyRNA *)self, self->arraydim, self->arrayoffset);
+}
static PyObject *pyrna_func_repr(BPy_FunctionRNA *self)
{
@@ -5841,7 +5853,7 @@ PyTypeObject pyrna_prop_array_Type = {
NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */
NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */
- NULL, /* subclassed */ /* tp_repr */
+ (reprfunc)pyrna_prop_array_repr, /* tp_repr */
/* Method suites for standard classes */
diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h
index 9ae5a4bd61d..542a0e349c7 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.h
+++ b/source/blender/python/mathutils/mathutils_Matrix.h
@@ -41,7 +41,7 @@ extern PyTypeObject matrix_access_Type;
# define MATRIX_ITEM_ASSERT(_mat, _row, _col) (void)0
#endif
-#define MATRIX_ITEM_INDEX_NUMROW(_totrow, _row, _col) ((_totrow * (_col)) + (_row))
+#define MATRIX_ITEM_INDEX_NUMROW(_totrow, _row, _col) (((_totrow) * (_col)) + (_row))
#define MATRIX_ITEM_INDEX(_mat, _row, _col) (MATRIX_ITEM_ASSERT(_mat, _row, _col),(((_mat)->num_row * (_col)) + (_row)))
#define MATRIX_ITEM_PTR( _mat, _row, _col) ((_mat)->matrix + MATRIX_ITEM_INDEX(_mat, _row, _col))
#define MATRIX_ITEM( _mat, _row, _col) ((_mat)->matrix [MATRIX_ITEM_INDEX(_mat, _row, _col)])
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index db2547e4fbe..388837af67a 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -220,6 +220,7 @@ void WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *wi
/* invoke callback, uses enum property named "type" */
void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op);
int WM_operator_smooth_viewtx_get(const struct wmOperator *op);
+int WM_menu_invoke_ex(struct bContext *C, struct wmOperator *op, int opcontext);
int WM_menu_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
/* invoke callback, confirm menu + exec */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 6ef8965a408..b4295bb2607 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1068,7 +1068,7 @@ int WM_operator_smooth_viewtx_get(const wmOperator *op)
}
/* invoke callback, uses enum property named "type" */
-int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+int WM_menu_invoke_ex(bContext *C, wmOperator *op, int opcontext)
{
PropertyRNA *prop = op->type->prop;
uiPopupMenu *pup;
@@ -1090,8 +1090,8 @@ int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
layout = UI_popup_menu_layout(pup);
/* set this so the default execution context is the same as submenus */
- uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN);
- uiItemsFullEnumO(layout, op->type->idname, RNA_property_identifier(prop), op->ptr->data, WM_OP_EXEC_REGION_WIN, 0);
+ uiLayoutSetOperatorContext(layout, opcontext);
+ uiItemsFullEnumO(layout, op->type->idname, RNA_property_identifier(prop), op->ptr->data, opcontext, 0);
UI_popup_menu_end(C, pup);
return OPERATOR_INTERFACE;
}
@@ -1099,6 +1099,11 @@ int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
return OPERATOR_CANCELLED;
}
+int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_REGION_WIN);
+}
+
/* generic enum search invoke popup */
static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op)
diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h
index 449612bc5fd..e2b95da29a1 100644
--- a/source/blender/windowmanager/wm_event_types.h
+++ b/source/blender/windowmanager/wm_event_types.h
@@ -343,37 +343,38 @@ enum {
/* *********** wmEvent.type helpers. ********** */
/* test whether the event is timer event */
-#define ISTIMER(event_type) (event_type >= TIMER && event_type <= TIMERF)
+#define ISTIMER(event_type) ((event_type) >= TIMER && (event_type) <= TIMERF)
/* for event checks */
/* only used for KM_TEXTINPUT, so assume that we want all user-inputtable ascii codes included */
/* UNUSED - see wm_eventmatch - BUG [#30479] */
-/* #define ISTEXTINPUT(event_type) (event_type >= ' ' && event_type <= 255) */
+/* #define ISTEXTINPUT(event_type) ((event_type) >= ' ' && (event_type) <= 255) */
/* note, an alternative could be to check 'event->utf8_buf' */
/* test whether the event is a key on the keyboard */
#define ISKEYBOARD(event_type) \
- ((event_type >= 0x0020 && event_type <= 0x00ff) || \
- (event_type >= 0x012c && event_type <= 0x013f))
+ (((event_type) >= 0x0020 && (event_type) <= 0x00ff) || \
+ ((event_type) >= 0x012c && (event_type) <= 0x013f))
/* test whether the event is a modifier key */
-#define ISKEYMODIFIER(event_type) ((event_type >= LEFTCTRLKEY && event_type <= LEFTSHIFTKEY) || event_type == OSKEY)
+#define ISKEYMODIFIER(event_type) \
+ (((event_type) >= LEFTCTRLKEY && (event_type) <= LEFTSHIFTKEY) || (event_type) == OSKEY)
/* test whether the event is a mouse button */
-#define ISMOUSE(event_type) (event_type >= LEFTMOUSE && event_type <= BUTTON7MOUSE)
+#define ISMOUSE(event_type) ((event_type) >= LEFTMOUSE && (event_type) <= BUTTON7MOUSE)
/* test whether the event is tweak event */
-#define ISTWEAK(event_type) (event_type >= EVT_TWEAK_L && event_type <= EVT_GESTURE)
+#define ISTWEAK(event_type) ((event_type) >= EVT_TWEAK_L && (event_type) <= EVT_GESTURE)
/* test whether the event is a NDOF event */
-#define ISNDOF(event_type) (event_type >= NDOF_MOTION && event_type < NDOF_LAST)
+#define ISNDOF(event_type) ((event_type) >= NDOF_MOTION && (event_type) < NDOF_LAST)
/* test whether event type is acceptable as hotkey, excluding modifiers */
#define ISHOTKEY(event_type) \
((ISKEYBOARD(event_type) || ISMOUSE(event_type) || ISNDOF(event_type)) && \
- (event_type != ESCKEY) && \
- (event_type >= LEFTCTRLKEY && event_type <= LEFTSHIFTKEY) == false && \
- (event_type >= UNKNOWNKEY && event_type <= GRLESSKEY) == false)
+ ((event_type) != ESCKEY) && \
+ ((event_type) >= LEFTCTRLKEY && (event_type) <= LEFTSHIFTKEY) == false && \
+ ((event_type) >= UNKNOWNKEY && (event_type) <= GRLESSKEY) == false)
/* internal helpers*/
#define _VA_IS_EVENT_MOD2(v, a) (CHECK_TYPE_INLINE(v, wmEvent *), \
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index eb0289e6909..6762e6752b0 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -707,6 +707,7 @@ int collada_export(struct Scene *sce,
int triangulate,
int use_object_instantiation,
+ int use_blender_profile,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
int open_sim) RET_ZERO
diff --git a/tests/gtests/blenlib/BLI_array_store_test.cc b/tests/gtests/blenlib/BLI_array_store_test.cc
new file mode 100644
index 00000000000..33fb454ec2f
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_array_store_test.cc
@@ -0,0 +1,815 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+extern "C" {
+#include "BLI_array_store.h"
+
+#include "MEM_guardedalloc.h"
+#include "BLI_sys_types.h"
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_array_utils.h"
+#include "BLI_string.h"
+#include "BLI_rand.h"
+#include "BLI_ressource_strings.h"
+}
+
+/* print memory savings */
+// #define DEBUG_PRINT
+
+
+/* -------------------------------------------------------------------- */
+/* Helper functions */
+
+#ifdef DEBUG_PRINT
+static void print_mem_saved(const char *id, const BArrayStore *bs)
+{
+ const double size_real = BLI_array_store_calc_size_compacted_get(bs);
+ const double size_expand = BLI_array_store_calc_size_expanded_get(bs);
+ const double percent = size_expand ? ((size_real / size_expand) * 100.0) : -1.0;
+ printf("%s: %.8f%%\n", id, percent);
+}
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/* Test Chunks (building data from list of chunks) */
+
+typedef struct TestChunnk {
+ struct TestChunnk *next, *prev;
+ const void *data;
+ size_t data_len;
+} TestChunnk;
+
+static TestChunnk *testchunk_list_add(ListBase *lb, const void *data, size_t data_len)
+{
+ TestChunnk *tc = (TestChunnk *)MEM_mallocN(sizeof(*tc), __func__);
+ tc->data = data;
+ tc->data_len = data_len;
+ BLI_addtail(lb, tc);
+
+ return tc;
+}
+
+#if 0
+static TestChunnk *testchunk_list_add_copydata(ListBase *lb, const void *data, size_t data_len)
+{
+ void *data_copy = MEM_mallocN(data_len, __func__);
+ memcpy(data_copy, data, data_len);
+ return testchunk_list_add(lb, data_copy, data_len);
+}
+#endif
+
+static void testchunk_list_free(ListBase *lb)
+{
+ for (TestChunnk *tc = (TestChunnk *)lb->first, *tb_next; tc; tc = tb_next) {
+ tb_next = tc->next;
+ MEM_freeN((void *)tc->data);
+ MEM_freeN(tc);
+ }
+ BLI_listbase_clear(lb);
+}
+
+#if 0
+static char *testchunk_as_data(
+ ListBase *lb,
+ size_t *r_data_len)
+{
+ size_t data_len = 0;
+ for (TestChunnk *tc = (TestChunnk *)lb->first; tc; tc = tc->next) {
+ data_len += tc->data_len;
+ }
+ char *data = (char *)MEM_mallocN(data_len, __func__);
+ size_t i = 0;
+ for (TestChunnk *tc = (TestChunnk *)lb->first; tc; tc = tc->next) {
+ memcpy(&data[i], tc->data, tc->data_len);
+ data_len += tc->data_len;
+ i += tc->data_len;
+ }
+ if (r_data_len) {
+ *r_data_len = i;
+ }
+ return data;
+}
+#endif
+
+static char *testchunk_as_data_array(
+ TestChunnk **tc_array, int tc_array_len,
+ size_t *r_data_len)
+{
+ size_t data_len = 0;
+ for (int tc_index = 0; tc_index < tc_array_len; tc_index++) {
+ data_len += tc_array[tc_index]->data_len;
+ }
+ char *data = (char *)MEM_mallocN(data_len, __func__);
+ size_t i = 0;
+ for (int tc_index = 0; tc_index < tc_array_len; tc_index++) {
+ TestChunnk *tc = tc_array[tc_index];
+ memcpy(&data[i], tc->data, tc->data_len);
+ i += tc->data_len;
+ }
+ if (r_data_len) {
+ *r_data_len = i;
+ }
+ return data;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Test Buffer */
+
+/* API to handle local allocation of data so we can compare it with the data in the array_store */
+typedef struct TestBuffer {
+ struct TestBuffer *next, *prev;
+ const void *data;
+ size_t data_len;
+
+ /* for reference */
+ BArrayState *state;
+} TestBuffer;
+
+static TestBuffer *testbuffer_list_add(ListBase *lb, const void *data, size_t data_len)
+{
+ TestBuffer *tb = (TestBuffer *)MEM_mallocN(sizeof(*tb), __func__);
+ tb->data = data;
+ tb->data_len = data_len;
+ tb->state = NULL;
+ BLI_addtail(lb, tb);
+ return tb;
+}
+
+static TestBuffer *testbuffer_list_add_copydata(ListBase *lb, const void *data, size_t data_len)
+{
+ void *data_copy = MEM_mallocN(data_len, __func__);
+ memcpy(data_copy, data, data_len);
+ return testbuffer_list_add(lb, data_copy, data_len);
+}
+
+static void testbuffer_list_state_from_data(
+ ListBase *lb,
+ const char *data, const size_t data_len)
+{
+ testbuffer_list_add_copydata(lb, (const void *)data, data_len);
+}
+
+/**
+ * A version of testbuffer_list_state_from_data that expand data by stride,
+ * handy so we can test data at different strides.
+ */
+static void testbuffer_list_state_from_data__stride_expand(
+ ListBase *lb,
+ const char *data, const size_t data_len,
+ const size_t stride)
+{
+ if (stride == 1) {
+ testbuffer_list_state_from_data(lb, data, data_len);
+ }
+ else {
+ const size_t data_stride_len = data_len * stride;
+ char *data_stride = (char *)MEM_mallocN(data_stride_len, __func__);
+
+ for (size_t i = 0, i_stride = 0; i < data_len; i += 1, i_stride += stride) {
+ memset(&data_stride[i_stride], data[i], stride);
+ }
+
+ testbuffer_list_add(lb, (const void *)data_stride, data_stride_len);
+ }
+}
+
+#define testbuffer_list_state_from_string_array(lb, data_array) \
+{ \
+ unsigned int i_ = 0; \
+ const char *data; \
+ while ((data = data_array[i_++])) { \
+ testbuffer_list_state_from_data(lb, data, strlen(data)); \
+ } \
+} ((void)0)
+
+//
+
+#define TESTBUFFER_STRINGS_CREATE(lb, ...) \
+{ \
+ BLI_listbase_clear(lb); \
+ const char *data_array[] = {__VA_ARGS__ NULL}; \
+ testbuffer_list_state_from_string_array((lb), data_array); \
+} ((void)0)
+
+/* test in both directions */
+#define TESTBUFFER_STRINGS_EX(bs, ...) \
+{ \
+ ListBase lb; \
+ TESTBUFFER_STRINGS_CREATE(&lb, __VA_ARGS__); \
+ \
+ testbuffer_run_tests(bs, &lb); \
+ \
+ testbuffer_list_free(&lb); \
+} ((void)0)
+
+#define TESTBUFFER_STRINGS(stride, chunk_count, ...) \
+{ \
+ ListBase lb; \
+ TESTBUFFER_STRINGS_CREATE(&lb, __VA_ARGS__); \
+ \
+ testbuffer_run_tests_simple(&lb, stride, chunk_count); \
+ \
+ testbuffer_list_free(&lb); \
+} ((void)0)
+
+static bool testbuffer_item_validate(TestBuffer *tb)
+{
+ size_t data_state_len;
+ bool ok = true;
+ void *data_state = BLI_array_store_state_data_get_alloc(tb->state, &data_state_len);
+ if (tb->data_len != data_state_len) {
+ ok = false;
+ }
+ else if (memcmp(data_state, tb->data, data_state_len) != 0) {
+ ok = false;
+ }
+ MEM_freeN(data_state);
+ return ok;
+}
+
+static bool testbuffer_list_validate(const ListBase *lb)
+{
+ for (TestBuffer *tb = (TestBuffer *)lb->first; tb; tb = tb->next) {
+ if (!testbuffer_item_validate(tb)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void testbuffer_list_data_randomize(ListBase *lb, unsigned int random_seed)
+{
+ for (TestBuffer *tb = (TestBuffer *)lb->first; tb; tb = tb->next) {
+ BLI_array_randomize((void *)tb->data, 1, tb->data_len, random_seed++);
+ }
+}
+
+static void testbuffer_list_store_populate(
+ BArrayStore *bs, ListBase *lb)
+{
+ for (TestBuffer *tb = (TestBuffer *)lb->first, *tb_prev = NULL; tb; tb_prev = tb, tb = tb->next) {
+ tb->state = BLI_array_store_state_add(bs, tb->data, tb->data_len, (tb_prev ? tb_prev->state : NULL));
+ }
+}
+
+static void testbuffer_list_store_clear(
+ BArrayStore *bs, ListBase *lb)
+{
+ for (TestBuffer *tb = (TestBuffer *)lb->first; tb; tb = tb->next) {
+ BLI_array_store_state_remove(bs, tb->state);
+ tb->state = NULL;
+ }
+}
+
+static void testbuffer_list_free(ListBase *lb)
+{
+ for (TestBuffer *tb = (TestBuffer *)lb->first, *tb_next; tb; tb = tb_next) {
+ tb_next = tb->next;
+ MEM_freeN((void *)tb->data);
+ MEM_freeN(tb);
+ }
+ BLI_listbase_clear(lb);
+}
+
+static void testbuffer_run_tests_single(
+ BArrayStore *bs, ListBase *lb)
+{
+ testbuffer_list_store_populate(bs, lb);
+ EXPECT_EQ(true, testbuffer_list_validate(lb));
+ EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+#ifdef DEBUG_PRINT
+ print_mem_saved("data", bs);
+#endif
+}
+
+/* avoid copy-paste code to run tests */
+static void testbuffer_run_tests(
+ BArrayStore *bs, ListBase *lb)
+{
+ /* forwards */
+ testbuffer_run_tests_single(bs, lb);
+ testbuffer_list_store_clear(bs, lb);
+
+ BLI_listbase_reverse(lb);
+
+ /* backwards */
+ testbuffer_run_tests_single(bs, lb);
+ testbuffer_list_store_clear(bs, lb);
+}
+
+static void testbuffer_run_tests_simple(
+ ListBase *lb,
+ const int stride, const int chunk_count)
+{
+ BArrayStore *bs = BLI_array_store_create(stride, chunk_count);
+ testbuffer_run_tests(bs, lb);
+ BLI_array_store_destroy(bs);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Basic Tests */
+
+TEST(array_store, Nop)
+{
+ BArrayStore *bs = BLI_array_store_create(1, 32);
+ BLI_array_store_destroy(bs);
+}
+
+TEST(array_store, NopState)
+{
+ BArrayStore *bs = BLI_array_store_create(1, 32);
+ const unsigned char data[] = "test";
+ BArrayState *state = BLI_array_store_state_add(bs, data, sizeof(data) - 1, NULL);
+ EXPECT_EQ(sizeof(data) - 1, BLI_array_store_state_size_get(state));
+ BLI_array_store_state_remove(bs, state);
+ BLI_array_store_destroy(bs);
+}
+
+TEST(array_store, Single)
+{
+ BArrayStore *bs = BLI_array_store_create(1, 32);
+ const char data_src[] = "test";
+ const char *data_dst;
+ BArrayState *state = BLI_array_store_state_add(bs, data_src, sizeof(data_src), NULL);
+ size_t data_dst_len;
+ data_dst = (char *)BLI_array_store_state_data_get_alloc(state, &data_dst_len);
+ EXPECT_STREQ(data_src, data_dst);
+ EXPECT_EQ(sizeof(data_src), data_dst_len);
+ BLI_array_store_destroy(bs);
+ MEM_freeN((void *)data_dst);
+}
+
+TEST(array_store, DoubleNop)
+{
+ BArrayStore *bs = BLI_array_store_create(1, 32);
+ const char data_src[] = "test";
+ const char *data_dst;
+
+ BArrayState *state_a = BLI_array_store_state_add(bs, data_src, sizeof(data_src), NULL);
+ BArrayState *state_b = BLI_array_store_state_add(bs, data_src, sizeof(data_src), state_a);
+
+ EXPECT_EQ(sizeof(data_src), BLI_array_store_calc_size_compacted_get(bs));
+ EXPECT_EQ(sizeof(data_src) * 2, BLI_array_store_calc_size_expanded_get(bs));
+
+ size_t data_dst_len;
+
+ data_dst = (char *)BLI_array_store_state_data_get_alloc(state_a, &data_dst_len);
+ EXPECT_STREQ(data_src, data_dst);
+ MEM_freeN((void *)data_dst);
+
+ data_dst = (char *)BLI_array_store_state_data_get_alloc(state_b, &data_dst_len);
+ EXPECT_STREQ(data_src, data_dst);
+ MEM_freeN((void *)data_dst);
+
+ EXPECT_EQ(sizeof(data_src), data_dst_len);
+ BLI_array_store_destroy(bs);
+}
+
+TEST(array_store, DoubleDiff)
+{
+ BArrayStore *bs = BLI_array_store_create(1, 32);
+ const char data_src_a[] = "test";
+ const char data_src_b[] = "####";
+ const char *data_dst;
+
+ BArrayState *state_a = BLI_array_store_state_add(bs, data_src_a, sizeof(data_src_a), NULL);
+ BArrayState *state_b = BLI_array_store_state_add(bs, data_src_b, sizeof(data_src_b), state_a);
+ size_t data_dst_len;
+
+ EXPECT_EQ(sizeof(data_src_a) * 2, BLI_array_store_calc_size_compacted_get(bs));
+ EXPECT_EQ(sizeof(data_src_a) * 2, BLI_array_store_calc_size_expanded_get(bs));
+
+ data_dst = (char *)BLI_array_store_state_data_get_alloc(state_a, &data_dst_len);
+ EXPECT_STREQ(data_src_a, data_dst);
+ MEM_freeN((void *)data_dst);
+
+ data_dst = (char *)BLI_array_store_state_data_get_alloc(state_b, &data_dst_len);
+ EXPECT_STREQ(data_src_b, data_dst);
+ MEM_freeN((void *)data_dst);
+
+ BLI_array_store_destroy(bs);
+}
+
+TEST(array_store, TextMixed)
+{
+ TESTBUFFER_STRINGS(1, 4, "",);
+ TESTBUFFER_STRINGS(1, 4, "test",);
+ TESTBUFFER_STRINGS(1, 4, "", "test",);
+ TESTBUFFER_STRINGS(1, 4, "test", "",);
+ TESTBUFFER_STRINGS(1, 4, "test", "", "test",);
+ TESTBUFFER_STRINGS(1, 4, "", "test", "",);
+}
+
+TEST(array_store, TextDupeIncreaseDecrease)
+{
+ ListBase lb;
+
+#define D "#1#2#3#4"
+ TESTBUFFER_STRINGS_CREATE(
+ &lb,
+ D,
+ D D,
+ D D D,
+ D D D D,
+ );
+
+ BArrayStore *bs = BLI_array_store_create(1, 8);
+
+ /* forward */
+ testbuffer_list_store_populate(bs, &lb);
+ EXPECT_EQ(true, testbuffer_list_validate(&lb));
+ EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+ EXPECT_EQ(strlen(D), BLI_array_store_calc_size_compacted_get(bs));
+
+ testbuffer_list_store_clear(bs, &lb);
+ BLI_listbase_reverse(&lb);
+
+ /* backwards */
+ testbuffer_list_store_populate(bs, &lb);
+ EXPECT_EQ(true, testbuffer_list_validate(&lb));
+ EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+ /* larger since first block doesn't de-duplicate */
+ EXPECT_EQ(strlen(D) * 4, BLI_array_store_calc_size_compacted_get(bs));
+
+#undef D
+ testbuffer_list_free(&lb); \
+
+ BLI_array_store_destroy(bs);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Plain Text Tests */
+
+/**
+ * Test that uses text input with different params for the array-store
+ * to ensure no corner cases fail.
+ */
+static void plain_text_helper(
+ const char *words, int words_len, const char word_delim,
+ const int stride, const int chunk_count, const int random_seed)
+{
+
+ ListBase lb;
+ BLI_listbase_clear(&lb);
+
+ for (int i = 0, i_prev = 0; i < words_len; i++) {
+ if (ELEM(words[i], word_delim, '\0')) {
+ if (i != i_prev) {
+ testbuffer_list_state_from_data__stride_expand(&lb, &words[i_prev], i - i_prev, stride);
+ }
+ i_prev = i;
+ }
+ }
+
+ if (random_seed) {
+ testbuffer_list_data_randomize(&lb, random_seed);
+ }
+
+ testbuffer_run_tests_simple(&lb, stride, chunk_count);
+
+ testbuffer_list_free(&lb);
+}
+
+/* split by '.' (multiple words) */
+#define WORDS words10k, sizeof(words10k)
+TEST(array_store, TextSentences_Chunk1) { plain_text_helper(WORDS, '.', 1, 1, 0); }
+TEST(array_store, TextSentences_Chunk2) { plain_text_helper(WORDS, '.', 1, 2, 0); }
+TEST(array_store, TextSentences_Chunk8) { plain_text_helper(WORDS, '.', 1, 8, 0); }
+TEST(array_store, TextSentences_Chunk32) { plain_text_helper(WORDS, '.', 1, 32, 0); }
+TEST(array_store, TextSentences_Chunk128) { plain_text_helper(WORDS, '.', 1, 128, 0); }
+TEST(array_store, TextSentences_Chunk1024) { plain_text_helper(WORDS, '.', 1, 1024, 0); }
+/* odd numbers */
+TEST(array_store, TextSentences_Chunk3) { plain_text_helper(WORDS, '.', 1, 3, 0); }
+TEST(array_store, TextSentences_Chunk13) { plain_text_helper(WORDS, '.', 1, 13, 0); }
+TEST(array_store, TextSentences_Chunk131) { plain_text_helper(WORDS, '.', 1, 131, 0); }
+
+/* split by ' ', individual words */
+TEST(array_store, TextWords_Chunk1) { plain_text_helper(WORDS, ' ', 1, 1, 0); }
+TEST(array_store, TextWords_Chunk2) { plain_text_helper(WORDS, ' ', 1, 2, 0); }
+TEST(array_store, TextWords_Chunk8) { plain_text_helper(WORDS, ' ', 1, 8, 0); }
+TEST(array_store, TextWords_Chunk32) { plain_text_helper(WORDS, ' ', 1, 32, 0); }
+TEST(array_store, TextWords_Chunk128) { plain_text_helper(WORDS, ' ', 1, 128, 0); }
+TEST(array_store, TextWords_Chunk1024) { plain_text_helper(WORDS, ' ', 1, 1024, 0); }
+/* odd numbers */
+TEST(array_store, TextWords_Chunk3) { plain_text_helper(WORDS, ' ', 1, 3, 0); }
+TEST(array_store, TextWords_Chunk13) { plain_text_helper(WORDS, ' ', 1, 13, 0); }
+TEST(array_store, TextWords_Chunk131) { plain_text_helper(WORDS, ' ', 1, 131, 0); }
+
+/* various tests with different strides & randomizing */
+TEST(array_store, TextSentencesRandom_Stride3_Chunk3) { plain_text_helper(WORDS, 'q', 3, 3, 7337); }
+TEST(array_store, TextSentencesRandom_Stride8_Chunk8) { plain_text_helper(WORDS, 'n', 8, 8, 5667); }
+TEST(array_store, TextSentencesRandom_Stride32_Chunk1) { plain_text_helper(WORDS, 'a', 1, 32, 1212); }
+TEST(array_store, TextSentencesRandom_Stride12_Chunk512) { plain_text_helper(WORDS, 'g', 12, 512, 9999); }
+TEST(array_store, TextSentencesRandom_Stride128_Chunk6) { plain_text_helper(WORDS, 'b', 20, 6, 1000); }
+
+#undef WORDS
+
+
+/* -------------------------------------------------------------------- */
+/* Random Data Tests */
+
+static unsigned int rand_range_i(RNG *rng, unsigned int min_i, unsigned int max_i, unsigned int step)
+{
+ if (min_i == max_i) {
+ return min_i;
+ }
+ BLI_assert(min_i <= max_i);
+ BLI_assert(((min_i % step) == 0) && ((max_i % step) == 0));
+ unsigned int range = (max_i - min_i);
+ unsigned int value = BLI_rng_get_uint(rng) % range;
+ value = (value / step) * step;
+ return min_i + value;
+}
+
+static void rand_bytes(RNG *rng, char *data, int data_len)
+{
+ BLI_assert(data_len != 0);
+ while (data_len--) {
+ *data = BLI_rng_get_uint(rng) % 256;
+ data++;
+ }
+}
+
+static void testbuffer_list_state_random_data(
+ ListBase *lb,
+ const size_t stride,
+ const size_t data_min_len, const size_t data_max_len,
+
+ const unsigned int mutate, RNG *rng)
+{
+ size_t data_len = rand_range_i(rng, data_min_len, data_max_len + stride, stride);
+ char *data = (char *)MEM_mallocN(data_len, __func__);
+
+ if (lb->last == NULL) {
+ rand_bytes(rng, data, data_len);
+ }
+ else {
+ TestBuffer *tb_last = (TestBuffer *)lb->last;
+ if (tb_last->data_len >= data_len) {
+ memcpy(data, tb_last->data, data_len);
+ }
+ else {
+ memcpy(data, tb_last->data, tb_last->data_len);
+ rand_bytes(rng, &data[tb_last->data_len], data_len - tb_last->data_len);
+ }
+
+ /* perform multiple small mutations to the array. */
+ for (int i = 0; i < mutate; i++) {
+ enum {
+ MUTATE_NOP = 0,
+ MUTATE_ADD,
+ MUTATE_REMOVE,
+ MUTATE_ROTATE,
+ MUTATE_RANDOMIZE,
+ MUTATE_TOTAL,
+ };
+
+ switch ((BLI_rng_get_uint(rng) % MUTATE_TOTAL)) {
+ case MUTATE_NOP:
+ {
+ break;
+ }
+ case MUTATE_ADD:
+ {
+ const unsigned int offset = rand_range_i(rng, 0, data_len, stride);
+ if (data_len < data_max_len) {
+ data_len += stride;
+ data = (char *)MEM_reallocN((void *)data, data_len);
+ memmove(&data[offset + stride], &data[offset], data_len - (offset + stride));
+ rand_bytes(rng, &data[offset], stride);
+ }
+ break;
+ }
+ case MUTATE_REMOVE:
+ {
+ const unsigned int offset = rand_range_i(rng, 0, data_len, stride);
+ if (data_len > data_min_len) {
+ memmove(&data[offset], &data[offset + stride], data_len - (offset + stride));
+ data_len -= stride;
+ }
+ break;
+ }
+ case MUTATE_ROTATE:
+ {
+ int items = data_len / stride;
+ if (items > 1) {
+ _bli_array_wrap(data, items, stride, (BLI_rng_get_uint(rng) % 2) ? -1 : 1);
+ }
+ break;
+ }
+ case MUTATE_RANDOMIZE:
+ {
+ if (data_len > 0) {
+ const unsigned int offset = rand_range_i(rng, 0, data_len - stride, stride);
+ rand_bytes(rng, &data[offset], stride);
+ }
+ break;
+ }
+ default:
+ BLI_assert(0);
+ }
+ }
+ }
+
+ testbuffer_list_add(lb, (const void *)data, data_len);
+}
+
+static void random_data_mutate_helper(
+ const int items_size_min, const int items_size_max, const int items_total,
+ const int stride, const int chunk_count,
+ const int random_seed, const int mutate)
+{
+
+
+ ListBase lb;
+ BLI_listbase_clear(&lb);
+
+ const size_t data_min_len = items_size_min * stride;
+ const size_t data_max_len = items_size_max * stride;
+
+ {
+ RNG *rng = BLI_rng_new(random_seed);
+ for (int i = 0; i < items_total; i++) {
+ testbuffer_list_state_random_data(&lb, stride, data_min_len, data_max_len, mutate, rng);
+ }
+ BLI_rng_free(rng);
+ }
+
+ testbuffer_run_tests_simple(&lb, stride, chunk_count);
+
+ testbuffer_list_free(&lb);
+}
+
+TEST(array_store, TestData_Stride1_Chunk32_Mutate2) { random_data_mutate_helper(0, 100, 400, 1, 32, 9779, 2); }
+TEST(array_store, TestData_Stride8_Chunk512_Mutate2) { random_data_mutate_helper(0, 128, 400, 8, 512, 1001, 2); }
+TEST(array_store, TestData_Stride12_Chunk48_Mutate2) { random_data_mutate_helper(200, 256, 400, 12, 48, 1331, 2); }
+TEST(array_store, TestData_Stride32_Chunk64_Mutate1) { random_data_mutate_helper(0, 256, 200, 32, 64, 3112, 1); }
+TEST(array_store, TestData_Stride32_Chunk64_Mutate8) { random_data_mutate_helper(0, 256, 200, 32, 64, 7117, 8); }
+
+
+/* -------------------------------------------------------------------- */
+/* Randomized Chunks Test */
+
+static void random_chunk_generate(
+ ListBase *lb,
+ const int chunks_per_buffer,
+ const int stride, const int chunk_count,
+ const int random_seed)
+{
+ RNG *rng = BLI_rng_new(random_seed);
+ const size_t chunk_size_bytes = stride * chunk_count;
+ for (int i = 0; i < chunks_per_buffer; i++) {
+ char *data_chunk = (char *)MEM_mallocN(chunk_size_bytes, __func__);
+ rand_bytes(rng, data_chunk, chunk_size_bytes);
+ testchunk_list_add(lb, data_chunk, chunk_size_bytes);
+ }
+ BLI_rng_free(rng);
+}
+
+/**
+ * Add random chunks, then re-order them to ensure chunk de-duplication is working.
+ */
+static void random_chunk_mutate_helper(
+ const int chunks_per_buffer, const int items_total,
+ const int stride, const int chunk_count,
+ const int random_seed)
+{
+ /* generate random chunks */
+
+ ListBase random_chunks;
+ BLI_listbase_clear(&random_chunks);
+ random_chunk_generate(&random_chunks, chunks_per_buffer, stride, chunk_count, random_seed);
+ TestChunnk **chunks_array = (TestChunnk **)MEM_mallocN(chunks_per_buffer * sizeof(TestChunnk *), __func__);
+ {
+ TestChunnk *tc = (TestChunnk *)random_chunks.first;
+ for (int i = 0; i < chunks_per_buffer; i++, tc = tc->next) {
+ chunks_array[i] = tc;
+ }
+ }
+
+ /* add and re-order each time */
+ ListBase lb;
+ BLI_listbase_clear(&lb);
+
+ {
+ RNG *rng = BLI_rng_new(random_seed);
+ for (int i = 0; i < items_total; i++) {
+ BLI_rng_shuffle_array(rng, chunks_array, sizeof(TestChunnk *), chunks_per_buffer);
+ size_t data_len;
+ char *data = testchunk_as_data_array(chunks_array, chunks_per_buffer, &data_len);
+ BLI_assert(data_len == chunks_per_buffer * chunk_count * stride);
+ testbuffer_list_add(&lb, (const void *)data, data_len);
+ }
+ BLI_rng_free(rng);
+ }
+
+ testchunk_list_free(&random_chunks);
+ MEM_freeN(chunks_array);
+
+ BArrayStore *bs = BLI_array_store_create(stride, chunk_count);
+ testbuffer_run_tests_single(bs, &lb);
+
+ size_t expected_size = chunks_per_buffer * chunk_count * stride;
+ EXPECT_EQ(expected_size, BLI_array_store_calc_size_compacted_get(bs));
+
+ BLI_array_store_destroy(bs);
+
+ testbuffer_list_free(&lb);
+
+}
+
+TEST(array_store, TestChunk_Rand8_Stride1_Chunk64) { random_chunk_mutate_helper(8, 100, 1, 64, 9779); }
+TEST(array_store, TestChunk_Rand32_Stride1_Chunk64) { random_chunk_mutate_helper(32, 100, 1, 64, 1331); }
+TEST(array_store, TestChunk_Rand64_Stride8_Chunk32) { random_chunk_mutate_helper(64, 100, 8, 32, 2772); }
+TEST(array_store, TestChunk_Rand31_Stride11_Chunk21) { random_chunk_mutate_helper(31, 100, 11, 21, 7117); }
+
+
+#if 0
+/* -------------------------------------------------------------------- */
+
+/* Test From Files (disabled, keep for local tests.) */
+
+void *file_read_binary_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size)
+{
+ FILE *fp = fopen(filepath, "rb");
+ void *mem = NULL;
+
+ if (fp) {
+ long int filelen_read;
+ fseek(fp, 0L, SEEK_END);
+ const long int filelen = ftell(fp);
+ if (filelen == -1) {
+ goto finally;
+ }
+ fseek(fp, 0L, SEEK_SET);
+
+ mem = MEM_mallocN(filelen + pad_bytes, __func__);
+ if (mem == NULL) {
+ goto finally;
+ }
+
+ filelen_read = fread(mem, 1, filelen, fp);
+ if ((filelen_read != filelen) || ferror(fp)) {
+ MEM_freeN(mem);
+ mem = NULL;
+ goto finally;
+ }
+
+ *r_size = filelen_read;
+
+finally:
+ fclose(fp);
+ }
+
+ return mem;
+}
+
+
+TEST(array_store, PlainTextFiles)
+{ ListBase lb;
+ BLI_listbase_clear(&lb);
+ BArrayStore *bs = BLI_array_store_create(1, 128);
+
+ for (int i = 0; i < 629; i++) {
+ char str[512];
+ BLI_snprintf(str, sizeof(str), "/src/py_array_cow/test_data/xz_data/%04d.c.xz", i);
+ // BLI_snprintf(str, sizeof(str), "/src/py_array_cow/test_data/c_code/%04d.c", i);
+ // printf("%s\n", str);
+ size_t data_len;
+ void *data;
+ data = file_read_binary_as_mem(str, 0, &data_len);
+
+ testbuffer_list_add(&lb, (const void *)data, data_len);
+ }
+
+ /* forwards */
+ testbuffer_list_store_populate(bs, &lb);
+ EXPECT_EQ(true, testbuffer_list_validate(&lb));
+ EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+#ifdef DEBUG_PRINT
+ print_mem_saved("source code forward", bs);
+#endif
+
+ testbuffer_list_store_clear(bs, &lb);
+ BLI_listbase_reverse(&lb);
+
+ /* backwards */
+ testbuffer_list_store_populate(bs, &lb);
+ EXPECT_EQ(true, testbuffer_list_validate(&lb));
+ EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+#ifdef DEBUG_PRINT
+ print_mem_saved("source code backwards", bs);
+#endif
+
+
+ testbuffer_list_free(&lb);
+ BLI_array_store_destroy(bs);
+}
+#endif
diff --git a/tests/gtests/blenlib/BLI_ghash_performance_test.cc b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
index 709302db021..fb32cb3f0a5 100644
--- a/tests/gtests/blenlib/BLI_ghash_performance_test.cc
+++ b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
@@ -21,6 +21,12 @@ extern "C" {
/* Resizing the hash has a huge cost over global filling operation! */
//#define GHASH_RESERVE
+/* Run the longest tests! */
+//#define GHASH_RUN_BIG
+
+/* Size of 'small case' ghash (number of entries). */
+#define TESTCASE_SIZE_SMALL 17
+
#define PRINTF_GHASH_STATS(_gh) \
{ \
double q, lf, var, pempty, poverloaded; \
@@ -32,7 +38,6 @@ extern "C" {
BLI_ghash_size(_gh), q, var, lf, pempty * 100.0, poverloaded * 100.0, bigb); \
} void (0)
-
/* Str: whole text, lines and words from a 'corpus' text. */
static void str_ghash_tests(GHash *ghash, const char *id)
@@ -223,12 +228,14 @@ TEST(ghash, IntGHash12000)
int_ghash_tests(ghash, "IntGHash - GHash - 12000", 12000);
}
+#ifdef GHASH_RUN_BIG
TEST(ghash, IntGHash100000000)
{
GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
int_ghash_tests(ghash, "IntGHash - GHash - 100000000", 100000000);
}
+#endif
TEST(ghash, IntMurmur2a12000)
{
@@ -237,13 +244,14 @@ TEST(ghash, IntMurmur2a12000)
int_ghash_tests(ghash, "IntGHash - Murmur - 12000", 12000);
}
+#ifdef GHASH_RUN_BIG
TEST(ghash, IntMurmur2a100000000)
{
GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
int_ghash_tests(ghash, "IntGHash - Murmur - 100000000", 100000000);
}
-
+#endif
/* Int: random 50M integers. */
@@ -302,12 +310,14 @@ TEST(ghash, IntRandGHash12000)
randint_ghash_tests(ghash, "RandIntGHash - GHash - 12000", 12000);
}
+#ifdef GHASH_RUN_BIG
TEST(ghash, IntRandGHash50000000)
{
GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
randint_ghash_tests(ghash, "RandIntGHash - GHash - 50000000", 50000000);
}
+#endif
TEST(ghash, IntRandMurmur2a12000)
{
@@ -316,12 +326,14 @@ TEST(ghash, IntRandMurmur2a12000)
randint_ghash_tests(ghash, "RandIntGHash - Murmur - 12000", 12000);
}
+#ifdef GHASH_RUN_BIG
TEST(ghash, IntRandMurmur2a50000000)
{
GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
randint_ghash_tests(ghash, "RandIntGHash - Murmur - 50000000", 50000000);
}
+#endif
static unsigned int ghashutil_tests_nohash_p(const void *p)
{
@@ -340,13 +352,14 @@ TEST(ghash, Int4NoHash12000)
randint_ghash_tests(ghash, "RandIntGHash - No Hash - 12000", 12000);
}
+#ifdef GHASH_RUN_BIG
TEST(ghash, Int4NoHash50000000)
{
GHash *ghash = BLI_ghash_new(ghashutil_tests_nohash_p, ghashutil_tests_cmp_p, __func__);
randint_ghash_tests(ghash, "RandIntGHash - No Hash - 50000000", 50000000);
}
-
+#endif
/* Int_v4: 20M of randomly-generated integer vectors. */
@@ -409,12 +422,14 @@ TEST(ghash, Int4GHash2000)
int4_ghash_tests(ghash, "Int4GHash - GHash - 2000", 2000);
}
+#ifdef GHASH_RUN_BIG
TEST(ghash, Int4GHash20000000)
{
GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__);
int4_ghash_tests(ghash, "Int4GHash - GHash - 20000000", 20000000);
}
+#endif
TEST(ghash, Int4Murmur2a2000)
{
@@ -423,9 +438,99 @@ TEST(ghash, Int4Murmur2a2000)
int4_ghash_tests(ghash, "Int4GHash - Murmur - 2000", 2000);
}
+#ifdef GHASH_RUN_BIG
TEST(ghash, Int4Murmur2a20000000)
{
GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p_murmur, BLI_ghashutil_uinthash_v4_cmp, __func__);
int4_ghash_tests(ghash, "Int4GHash - Murmur - 20000000", 20000000);
}
+#endif
+
+/* MultiSmall: create and manipulate a lot of very small ghashes (90% < 10 items, 9% < 100 items, 1% < 1000 items). */
+
+static void multi_small_ghash_tests_one(GHash *ghash, RNG *rng, const unsigned int nbr)
+{
+ unsigned int *data = (unsigned int *)MEM_mallocN(sizeof(*data) * (size_t)nbr, __func__);
+ unsigned int *dt;
+ unsigned int i;
+
+ for (i = nbr, dt = data; i--; dt++) {
+ *dt = BLI_rng_get_uint(rng);
+ }
+
+#ifdef GHASH_RESERVE
+ BLI_ghash_reserve(ghash, nbr);
+#endif
+
+ for (i = nbr, dt = data; i--; dt++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*dt), SET_UINT_IN_POINTER(*dt));
+ }
+
+ for (i = nbr, dt = data; i--; dt++) {
+ void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*dt));
+ EXPECT_EQ(*dt, GET_UINT_FROM_POINTER(v));
+ }
+
+ BLI_ghash_clear(ghash, NULL, NULL);
+}
+
+static void multi_small_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr)
+{
+ printf("\n========== STARTING %s ==========\n", id);
+
+ RNG *rng = BLI_rng_new(0);
+
+ TIMEIT_START(multi_small_ghash);
+
+ unsigned int i = nbr;
+ while (i--) {
+ const int nbr = 1 + (BLI_rng_get_int(rng) % TESTCASE_SIZE_SMALL) * (!(i % 100) ? 100 : (!(i % 10) ? 10 : 1));
+ multi_small_ghash_tests_one(ghash, rng, nbr);
+ }
+
+ TIMEIT_END(multi_small_ghash);
+
+ TIMEIT_START(multi_small2_ghash);
+
+ unsigned int i = nbr;
+ while (i--) {
+ const int nbr = 1 + (BLI_rng_get_int(rng) % TESTCASE_SIZE_SMALL) / 2 * (!(i % 100) ? 100 : (!(i % 10) ? 10 : 1));
+ multi_small_ghash_tests_one(ghash, rng, nbr);
+ }
+
+ TIMEIT_END(multi_small2_ghash);
+
+ BLI_ghash_free(ghash, NULL, NULL);
+ BLI_rng_free(rng);
+
+ printf("========== ENDED %s ==========\n\n", id);
+}
+
+TEST(ghash, MultiRandIntGHash2000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+
+ multi_small_ghash_tests(ghash, "MultiSmall RandIntGHash - GHash - 2000", 2000);
+}
+
+TEST(ghash, MultiRandIntGHash200000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+
+ multi_small_ghash_tests(ghash, "MultiSmall RandIntGHash - GHash - 200000", 200000);
+}
+
+TEST(ghash, MultiRandIntMurmur2a2000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
+
+ multi_small_ghash_tests(ghash, "MultiSmall RandIntGHash - Murmur2a - 2000", 2000);
+}
+
+TEST(ghash, MultiRandIntMurmur2a200000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
+
+ multi_small_ghash_tests(ghash, "MultiSmall RandIntGHash - Murmur2a - 200000", 200000);
+}
diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt
index 5e6bddcdeab..12112e7a481 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -35,6 +35,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}")
+BLENDER_TEST(BLI_array_store "bf_blenlib")
BLENDER_TEST(BLI_array_utils "bf_blenlib")
BLENDER_TEST(BLI_stack "bf_blenlib")
BLENDER_TEST(BLI_math_color "bf_blenlib")