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:
authorSergey Sharybin <sergey.vfx@gmail.com>2017-02-17 15:54:04 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2017-02-17 16:18:25 +0300
commita908e63590cf8579894642df095c64dbe3abed01 (patch)
tree3bbd3fbf583d49f094b193c7b4755de8a3fc510e
parenta644f2b46c54259809bf2c88ee26465aa33e7b37 (diff)
parentd41451a0ca5053885deffce2bf603fc6c488ddf4 (diff)
Merge branch 'master' into cycles_split_kernel
-rw-r--r--CMakeLists.txt1
-rw-r--r--build_files/buildbot/slave_compile.py2
-rw-r--r--intern/CMakeLists.txt2
-rw-r--r--intern/cycles/CMakeLists.txt2
-rw-r--r--intern/cycles/blender/blender_mesh.cpp220
-rw-r--r--intern/cycles/blender/blender_shader.cpp6
-rw-r--r--intern/cycles/blender/blender_util.h31
-rw-r--r--intern/cycles/bvh/bvh.cpp10
-rw-r--r--intern/cycles/bvh/bvh.h2
-rw-r--r--intern/cycles/bvh/bvh_build.cpp36
-rw-r--r--intern/cycles/bvh/bvh_build.h4
-rw-r--r--intern/cycles/bvh/bvh_params.h1
-rw-r--r--intern/cycles/kernel/bvh/bvh.h27
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h28
-rw-r--r--intern/cycles/kernel/kernel_globals.h5
-rw-r--r--intern/cycles/kernel/kernel_shadow.h611
-rw-r--r--intern/cycles/kernel/kernel_textures.h2
-rw-r--r--intern/cycles/kernel/kernel_types.h4
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel.cu27
-rw-r--r--intern/cycles/kernel/svm/svm_image.h1
-rw-r--r--intern/cycles/kernel/svm/svm_math_util.h53
-rw-r--r--intern/cycles/render/bake.h2
-rw-r--r--intern/cycles/render/light.cpp11
-rw-r--r--intern/cycles/render/mesh.cpp7
-rw-r--r--intern/cycles/render/scene.h1
-rw-r--r--intern/cycles/test/render_graph_finalize_test.cpp6
-rw-r--r--intern/cycles/test/util_aligned_malloc_test.cpp2
-rw-r--r--intern/cycles/test/util_path_test.cpp100
-rw-r--r--intern/cycles/test/util_string_test.cpp64
-rw-r--r--intern/utfconv/utfconv.h2
-rw-r--r--make.bat25
-rw-r--r--release/datafiles/blender_icons.svg88
-rw-r--r--release/datafiles/blender_icons16/icon16_normalize_fcurves.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_normalize_fcurves.datbin0 -> 4120 bytes
-rw-r--r--release/scripts/freestyle/modules/parameter_editor.py12
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py54
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py9
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py42
-rw-r--r--release/scripts/startup/bl_ui/space_time.py6
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py14
-rw-r--r--source/blender/alembic/intern/abc_archive.cc22
-rw-r--r--source/blender/alembic/intern/abc_curves.cc12
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc21
-rw-r--r--source/blender/alembic/intern/abc_hair.cc5
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc18
-rw-r--r--source/blender/alembic/intern/abc_nurbs.cc4
-rw-r--r--source/blender/alembic/intern/abc_object.cc6
-rw-r--r--source/blender/alembic/intern/abc_points.cc2
-rw-r--r--source/blender/alembic/intern/abc_transform.cc4
-rw-r--r--source/blender/alembic/intern/abc_util.cc4
-rw-r--r--source/blender/alembic/intern/abc_util.h8
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h14
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h1
-rw-r--r--source/blender/blenkernel/BKE_object.h2
-rw-r--r--source/blender/blenkernel/BKE_texture.h7
-rw-r--r--source/blender/blenkernel/intern/appdir.c2
-rw-r--r--source/blender/blenkernel/intern/armature.c14
-rw-r--r--source/blender/blenkernel/intern/blender.c2
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c455
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c46
-rw-r--r--source/blender/blenkernel/intern/customdata.c2
-rw-r--r--source/blender/blenkernel/intern/image.c8
-rw-r--r--source/blender/blenkernel/intern/lamp.c8
-rw-r--r--source/blender/blenkernel/intern/mesh.c347
-rw-r--r--source/blender/blenkernel/intern/object.c60
-rw-r--r--source/blender/blenkernel/intern/particle.c5
-rw-r--r--source/blender/blenkernel/intern/sequencer.c89
-rw-r--r--source/blender/blenkernel/intern/sound.c4
-rw-r--r--source/blender/blenkernel/intern/text.c16
-rw-r--r--source/blender/blenkernel/intern/texture.c15
-rw-r--r--source/blender/blenlib/BLI_dynlib.h2
-rw-r--r--source/blender/blenlib/BLI_sys_types.h5
-rw-r--r--source/blender/blenlib/PIL_time_utildefines.h5
-rw-r--r--source/blender/blenlib/intern/dynlib.c4
-rw-r--r--source/blender/blenlib/intern/polyfill2d.c17
-rw-r--r--source/blender/blenloader/intern/readfile.c3
-rw-r--r--source/blender/blenloader/intern/writefile.c364
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc6
-rw-r--r--source/blender/editors/animation/anim_draw.c93
-rw-r--r--source/blender/editors/animation/anim_ops.c25
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c5
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c8
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h4
-rw-r--r--source/blender/editors/include/UI_icons.h2
-rw-r--r--source/blender/editors/interface/interface_widgets.c2
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c2
-rw-r--r--source/blender/editors/object/object_vgroup.c61
-rw-r--r--source/blender/editors/render/render_opengl.c8
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c15
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c2
-rw-r--r--source/blender/editors/transform/transform.c27
-rw-r--r--source/blender/editors/transform/transform.h4
-rw-r--r--source/blender/editors/transform/transform_conversions.c7
-rw-r--r--source/blender/editors/transform/transform_snap.c2
-rw-r--r--source/blender/editors/transform/transform_snap_object.c1018
-rw-r--r--source/blender/imbuf/IMB_colormanagement.h12
-rw-r--r--source/blender/imbuf/intern/colormanagement.c173
-rw-r--r--source/blender/makesdna/DNA_scene_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_scene.c46
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c209
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c4
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c34
-rw-r--r--tests/gtests/blenlib/BLI_array_store_test.cc40
-rw-r--r--tests/gtests/blenlib/BLI_array_utils_test.cc36
-rw-r--r--tests/gtests/blenlib/BLI_ghash_performance_test.cc18
-rw-r--r--tests/gtests/blenlib/BLI_ghash_test.cc34
-rw-r--r--tests/gtests/blenlib/BLI_hash_mm2a_test.cc16
-rw-r--r--tests/gtests/blenlib/BLI_listbase_test.cc26
-rw-r--r--tests/gtests/blenlib/BLI_path_util_test.cc16
-rw-r--r--tests/gtests/blenlib/BLI_polyfill2d_test.cc10
-rw-r--r--tests/gtests/blenlib/BLI_stack_test.cc32
-rw-r--r--tests/gtests/blenlib/BLI_string_test.cc102
-rw-r--r--tests/gtests/blenlib/BLI_string_utf8_test.cc2
-rw-r--r--tests/gtests/bmesh/bmesh_core_test.cc18
-rw-r--r--tests/gtests/guardedalloc/guardedalloc_alignment_test.cc2
-rw-r--r--tests/python/CMakeLists.txt12
-rwxr-xr-xtests/python/cycles_render_tests.py47
119 files changed, 3148 insertions, 2162 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 092de982b9d..1cc3e02e03a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -445,6 +445,7 @@ option(WITH_BOOST "Enable features depending on boost" ON)
# Unit testsing
option(WITH_GTESTS "Enable GTest unit testing" OFF)
+option(WITH_OPENGL_TESTS "Enable OpenGL related unit testing (Experimental)" OFF)
# Documentation
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index 76d538ad578..860dd1174cf 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -72,10 +72,8 @@ if 'cmake' in builder:
# Set up OSX architecture
if builder.endswith('x86_64_10_6_cmake'):
cmake_extra_options.append('-DCMAKE_OSX_ARCHITECTURES:STRING=x86_64')
- cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda8-hack/bin/nvcc')
cmake_extra_options.append('-DWITH_CODEC_QUICKTIME=OFF')
cmake_extra_options.append('-DCMAKE_OSX_DEPLOYMENT_TARGET=10.6')
- build_cubins = False
elif builder.startswith('win'):
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index 9a5476772ab..dd9889c81ba 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -62,7 +62,7 @@ if(WITH_IK_ITASC)
add_subdirectory(itasc)
endif()
-if(WITH_IK_SOLVER OR WITH_GAMEENGINE OR WITH_MOD_BOOLEAN)
+if(WITH_GAMEENGINE)
add_subdirectory(moto)
endif()
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 79c1c3e3e82..31fa15a2042 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -74,6 +74,7 @@ elseif(CMAKE_COMPILER_IS_GNUCC)
if(CXX_HAS_AVX2)
set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c -mfpmath=sse")
endif()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math -fno-finite-math-only")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
@@ -89,6 +90,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(CXX_HAS_AVX2)
set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c")
endif()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math -fno-finite-math-only")
endif()
if(CXX_HAS_SSE)
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 85117cfff7b..a1ff81e750a 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -27,6 +27,7 @@
#include "subd_patch.h"
#include "subd_split.h"
+#include "util_algorithm.h"
#include "util_foreach.h"
#include "util_logging.h"
#include "util_math.h"
@@ -525,69 +526,177 @@ static void attr_create_uv_map(Scene *scene,
}
/* Create vertex pointiness attributes. */
+
+/* Compare vertices by sum of their coordinates. */
+class VertexAverageComparator {
+public:
+ VertexAverageComparator(const array<float3>& verts)
+ : verts_(verts) {
+ }
+
+ bool operator()(const int& vert_idx_a, const int& vert_idx_b)
+ {
+ const float3 &vert_a = verts_[vert_idx_a];
+ const float3 &vert_b = verts_[vert_idx_b];
+ if(vert_a == vert_b) {
+ /* Special case for doubles, so we ensure ordering. */
+ return vert_idx_a > vert_idx_b;
+ }
+ const float x1 = vert_a.x + vert_a.y + vert_a.z;
+ const float x2 = vert_b.x + vert_b.y + vert_b.z;
+ return x1 < x2;
+ }
+
+protected:
+ const array<float3>& verts_;
+};
+
static void attr_create_pointiness(Scene *scene,
Mesh *mesh,
BL::Mesh& b_mesh,
bool subdivision)
{
- if(mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
- const int numverts = b_mesh.vertices.length();
- AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes;
- Attribute *attr = attributes.add(ATTR_STD_POINTINESS);
- float *data = attr->data_float();
- int *counter = new int[numverts];
- float *raw_data = new float[numverts];
- float3 *edge_accum = new float3[numverts];
-
- /* Calculate pointiness using single ring neighborhood. */
- memset(counter, 0, sizeof(int) * numverts);
- memset(raw_data, 0, sizeof(float) * numverts);
- memset(edge_accum, 0, sizeof(float3) * numverts);
- BL::Mesh::edges_iterator e;
- int i = 0;
- for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
- int v0 = b_mesh.edges[i].vertices()[0],
- v1 = b_mesh.edges[i].vertices()[1];
- float3 co0 = get_float3(b_mesh.vertices[v0].co()),
- co1 = get_float3(b_mesh.vertices[v1].co());
- float3 edge = normalize(co1 - co0);
- edge_accum[v0] += edge;
- edge_accum[v1] += -edge;
- ++counter[v0];
- ++counter[v1];
- }
- i = 0;
- BL::Mesh::vertices_iterator v;
- for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i) {
- if(counter[i] > 0) {
- float3 normal = get_float3(b_mesh.vertices[i].normal());
- float angle = safe_acosf(dot(normal, edge_accum[i] / counter[i]));
- raw_data[i] = angle * M_1_PI_F;
+ if(!mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
+ return;
+ }
+ const int num_verts = b_mesh.vertices.length();
+ /* STEP 1: Find out duplicated vertices and point duplicates to a single
+ * original vertex.
+ */
+ vector<int> sorted_vert_indeices(num_verts);
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ sorted_vert_indeices[vert_index] = vert_index;
+ }
+ VertexAverageComparator compare(mesh->verts);
+ sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare);
+ /* This array stores index of the original vertex for the given vertex
+ * index.
+ */
+ vector<int> vert_orig_index(num_verts);
+ for(int sorted_vert_index = 0;
+ sorted_vert_index < num_verts;
+ ++sorted_vert_index)
+ {
+ const int vert_index = sorted_vert_indeices[sorted_vert_index];
+ const float3 &vert_co = mesh->verts[vert_index];
+ bool found = false;
+ for(int other_sorted_vert_index = sorted_vert_index + 1;
+ other_sorted_vert_index < num_verts;
+ ++other_sorted_vert_index)
+ {
+ const int other_vert_index =
+ sorted_vert_indeices[other_sorted_vert_index];
+ const float3 &other_vert_co = mesh->verts[other_vert_index];
+ /* We are too far away now, we wouldn't have duplicate. */
+ if ((other_vert_co.x + other_vert_co.y + other_vert_co.z) -
+ (vert_co.x + vert_co.y + vert_co.z) > 3 * FLT_EPSILON)
+ {
+ break;
}
- else {
- raw_data[i] = 0.0f;
+ /* Found duplicate. */
+ if(len_squared(other_vert_co - vert_co) < FLT_EPSILON) {
+ found = true;
+ vert_orig_index[vert_index] = other_vert_index;
+ break;
}
}
-
- /* Blur vertices to approximate 2 ring neighborhood. */
- memset(counter, 0, sizeof(int) * numverts);
- memcpy(data, raw_data, sizeof(float) * numverts);
- i = 0;
- for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
- int v0 = b_mesh.edges[i].vertices()[0],
- v1 = b_mesh.edges[i].vertices()[1];
- data[v0] += raw_data[v1];
- data[v1] += raw_data[v0];
- ++counter[v0];
- ++counter[v1];
+ if(!found) {
+ vert_orig_index[vert_index] = vert_index;
}
- for(i = 0; i < numverts; ++i) {
- data[i] /= counter[i] + 1;
+ }
+ /* Make sure we always points to the very first orig vertex. */
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ int orig_index = vert_orig_index[vert_index];
+ while(orig_index != vert_orig_index[orig_index]) {
+ orig_index = vert_orig_index[orig_index];
}
-
- delete [] counter;
- delete [] raw_data;
- delete [] edge_accum;
+ vert_orig_index[vert_index] = orig_index;
+ }
+ sorted_vert_indeices.free_memory();
+ /* STEP 2: Calculate vertex normals taking into account their possible
+ * duplicates which gets "welded" together.
+ */
+ vector<float3> vert_normal(num_verts, make_float3(0.0f, 0.0f, 0.0f));
+ /* First we accumulate all vertex normals in the original index. */
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const float3 normal = get_float3(b_mesh.vertices[vert_index].normal());
+ const int orig_index = vert_orig_index[vert_index];
+ vert_normal[orig_index] += normal;
+ }
+ /* Then we normalize the accumulated result and flush it to all duplicates
+ * as well.
+ */
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ vert_normal[vert_index] = normalize(vert_normal[orig_index]);
+ }
+ /* STEP 3: Calculate pointiness using single ring neighborhood. */
+ vector<int> counter(num_verts, 0);
+ vector<float> raw_data(num_verts, 0.0f);
+ vector<float3> edge_accum(num_verts, make_float3(0.0f, 0.0f, 0.0f));
+ BL::Mesh::edges_iterator e;
+ EdgeMap visited_edges;
+ int edge_index = 0;
+ memset(&counter[0], 0, sizeof(int) * counter.size());
+ for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
+ const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
+ v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
+ if(visited_edges.exists(v0, v1)) {
+ continue;
+ }
+ visited_edges.insert(v0, v1);
+ float3 co0 = get_float3(b_mesh.vertices[v0].co()),
+ co1 = get_float3(b_mesh.vertices[v1].co());
+ float3 edge = normalize(co1 - co0);
+ edge_accum[v0] += edge;
+ edge_accum[v1] += -edge;
+ ++counter[v0];
+ ++counter[v1];
+ }
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ if(orig_index != vert_index) {
+ /* Skip duplicates, they'll be overwritten later on. */
+ continue;
+ }
+ if(counter[vert_index] > 0) {
+ const float3 normal = vert_normal[vert_index];
+ const float angle =
+ safe_acosf(dot(normal,
+ edge_accum[vert_index] / counter[vert_index]));
+ raw_data[vert_index] = angle * M_1_PI_F;
+ }
+ else {
+ raw_data[vert_index] = 0.0f;
+ }
+ }
+ /* STEP 3: Blur vertices to approximate 2 ring neighborhood. */
+ AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes;
+ Attribute *attr = attributes.add(ATTR_STD_POINTINESS);
+ float *data = attr->data_float();
+ memcpy(data, &raw_data[0], sizeof(float) * raw_data.size());
+ memset(&counter[0], 0, sizeof(int) * counter.size());
+ edge_index = 0;
+ visited_edges.clear();
+ for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
+ const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
+ v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
+ if(visited_edges.exists(v0, v1)) {
+ continue;
+ }
+ visited_edges.insert(v0, v1);
+ data[v0] += raw_data[v1];
+ data[v1] += raw_data[v0];
+ ++counter[v0];
+ ++counter[v1];
+ }
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ data[vert_index] /= counter[vert_index] + 1;
+ }
+ /* STEP 4: Copy attribute to the duplicated vertices. */
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ data[vert_index] = data[orig_index];
}
}
@@ -656,9 +765,6 @@ static void create_mesh(Scene *scene,
generated[i++] = get_float3(v->undeformed_co())*size - loc;
}
- /* Create needed vertex attributes. */
- attr_create_pointiness(scene, mesh, b_mesh, subdivision);
-
/* create faces */
vector<int> nverts(numfaces);
vector<int> face_flags(numfaces, FACE_FLAG_NONE);
@@ -718,6 +824,7 @@ static void create_mesh(Scene *scene,
/* Create all needed attributes.
* The calculate functions will check whether they're needed or not.
*/
+ attr_create_pointiness(scene, mesh, b_mesh, subdivision);
attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags, subdivision);
attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags, subdivision, subdivide_uvs);
@@ -1178,4 +1285,3 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
}
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index f6ec015e1b8..8baa53fc2ec 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -609,7 +609,8 @@ static ShaderNode *add_node(Scene *scene,
bool is_builtin = b_image.packed_file() ||
b_image.source() == BL::Image::source_GENERATED ||
b_image.source() == BL::Image::source_MOVIE ||
- b_engine.is_preview();
+ (b_engine.is_preview() &&
+ b_image.source() != BL::Image::source_SEQUENCE);
if(is_builtin) {
/* for builtin images we're using image datablock name to find an image to
@@ -662,7 +663,8 @@ static ShaderNode *add_node(Scene *scene,
bool is_builtin = b_image.packed_file() ||
b_image.source() == BL::Image::source_GENERATED ||
b_image.source() == BL::Image::source_MOVIE ||
- b_engine.is_preview();
+ (b_engine.is_preview() &&
+ b_image.source() != BL::Image::source_SEQUENCE);
if(is_builtin) {
int scene_frame = b_scene.frame_current();
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index b67834cdea3..4411181dbcc 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -19,6 +19,7 @@
#include "mesh.h"
+#include "util_algorithm.h"
#include "util_map.h"
#include "util_path.h"
#include "util_set.h"
@@ -79,6 +80,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
}
else {
me.split_faces();
+ me.calc_normals_split();
}
}
if(subdivision_type == Mesh::SUBDIVISION_NONE) {
@@ -786,6 +788,35 @@ struct ParticleSystemKey {
}
};
+class EdgeMap {
+public:
+ EdgeMap() {
+ }
+
+ void clear() {
+ edges_.clear();
+ }
+
+ void insert(int v0, int v1) {
+ get_sorted_verts(v0, v1);
+ edges_.insert(std::pair<int, int>(v0, v1));
+ }
+
+ bool exists(int v0, int v1) {
+ get_sorted_verts(v0, v1);
+ return edges_.find(std::pair<int, int>(v0, v1)) != edges_.end();
+ }
+
+protected:
+ void get_sorted_verts(int& v0, int& v1) {
+ if(v0 > v1) {
+ swap(v0, v1);
+ }
+ }
+
+ set< std::pair<int, int> > edges_;
+};
+
CCL_NAMESPACE_END
#endif /* __BLENDER_UTIL_H__ */
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 874a4246d1d..1fb2f371a0f 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -81,6 +81,7 @@ void BVH::build(Progress& progress)
pack.prim_type,
pack.prim_index,
pack.prim_object,
+ pack.prim_time,
params,
progress);
BVHNode *root = bvh_build.run();
@@ -256,6 +257,10 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
pack.leaf_nodes.resize(leaf_nodes_size);
pack.object_node.resize(objects.size());
+ if(params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0) {
+ pack.prim_time.resize(prim_index_size);
+ }
+
int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
int *pack_prim_type = (pack.prim_type.size())? &pack.prim_type[0]: NULL;
int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL;
@@ -264,6 +269,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
uint *pack_prim_tri_index = (pack.prim_tri_index.size())? &pack.prim_tri_index[0]: NULL;
int4 *pack_nodes = (pack.nodes.size())? &pack.nodes[0]: NULL;
int4 *pack_leaf_nodes = (pack.leaf_nodes.size())? &pack.leaf_nodes[0]: NULL;
+ float2 *pack_prim_time = (pack.prim_time.size())? &pack.prim_time[0]: NULL;
/* merge */
foreach(Object *ob, objects) {
@@ -309,6 +315,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
int *bvh_prim_type = &bvh->pack.prim_type[0];
uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0];
+ float2 *bvh_prim_time = bvh->pack.prim_time.size()? &bvh->pack.prim_time[0]: NULL;
for(size_t i = 0; i < bvh_prim_index_size; i++) {
if(bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
@@ -324,6 +331,9 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
+ if(bvh_prim_time != NULL) {
+ pack_prim_time[pack_prim_index_offset] = bvh_prim_time[i];
+ }
pack_prim_index_offset++;
}
}
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 35f4d305883..08f41fc736f 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -68,6 +68,8 @@ struct PackedBVH {
array<int> prim_index;
/* mapping from BVH primitive index, to the object id of that primitive. */
array<int> prim_object;
+ /* Time range of BVH primitive. */
+ array<float2> prim_time;
/* index of the root node. */
int root_index;
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index a2f8b33cb0b..fcbc50f4f6f 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -93,12 +93,14 @@ BVHBuild::BVHBuild(const vector<Object*>& objects_,
array<int>& prim_type_,
array<int>& prim_index_,
array<int>& prim_object_,
+ array<float2>& prim_time_,
const BVHParams& params_,
Progress& progress_)
: objects(objects_),
prim_type(prim_type_),
prim_index(prim_index_),
prim_object(prim_object_),
+ prim_time(prim_time_),
params(params_),
progress(progress_),
progress_start_time(0.0),
@@ -465,6 +467,9 @@ BVHNode* BVHBuild::run()
}
spatial_free_index = 0;
+ need_prim_time = params.num_motion_curve_steps > 0 ||
+ params.num_motion_triangle_steps > 0;
+
/* init progress updates */
double build_start_time;
build_start_time = progress_start_time = time_dt();
@@ -475,6 +480,12 @@ BVHNode* BVHBuild::run()
prim_type.resize(references.size());
prim_index.resize(references.size());
prim_object.resize(references.size());
+ if(need_prim_time) {
+ prim_time.resize(references.size());
+ }
+ else {
+ prim_time.resize(0);
+ }
/* build recursively */
BVHNode *rootnode;
@@ -849,6 +860,9 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
prim_type[start] = ref->prim_type();
prim_index[start] = ref->prim_index();
prim_object[start] = ref->prim_object();
+ if(need_prim_time) {
+ prim_time[start] = make_float2(ref->time_from(), ref->time_to());
+ }
uint visibility = objects[ref->prim_object()]->visibility;
BVHNode *leaf_node = new LeafNode(ref->bounds(), visibility, start, start+1);
@@ -896,6 +910,7 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
vector<int, LeafStackAllocator> p_type[PRIMITIVE_NUM_TOTAL];
vector<int, LeafStackAllocator> p_index[PRIMITIVE_NUM_TOTAL];
vector<int, LeafStackAllocator> p_object[PRIMITIVE_NUM_TOTAL];
+ vector<float2, LeafStackAllocator> p_time[PRIMITIVE_NUM_TOTAL];
vector<BVHReference, LeafReferenceStackAllocator> p_ref[PRIMITIVE_NUM_TOTAL];
/* TODO(sergey): In theory we should be able to store references. */
@@ -918,6 +933,8 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
p_type[type_index].push_back(ref.prim_type());
p_index[type_index].push_back(ref.prim_index());
p_object[type_index].push_back(ref.prim_object());
+ p_time[type_index].push_back(make_float2(ref.time_from(),
+ ref.time_to()));
bounds[type_index].grow(ref.bounds());
visibility[type_index] |= objects[ref.prim_object()]->visibility;
@@ -947,9 +964,13 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
vector<int, LeafStackAllocator> local_prim_type,
local_prim_index,
local_prim_object;
+ vector<float2, LeafStackAllocator> local_prim_time;
local_prim_type.resize(num_new_prims);
local_prim_index.resize(num_new_prims);
local_prim_object.resize(num_new_prims);
+ if(need_prim_time) {
+ local_prim_time.resize(num_new_prims);
+ }
for(int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) {
int num = (int)p_type[i].size();
if(num != 0) {
@@ -962,6 +983,9 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
local_prim_type[index] = p_type[i][j];
local_prim_index[index] = p_index[i][j];
local_prim_object[index] = p_object[i][j];
+ if(need_prim_time) {
+ local_prim_time[index] = p_time[i][j];
+ }
if(params.use_unaligned_nodes && !alignment_found) {
alignment_found =
unaligned_heuristic.compute_aligned_space(p_ref[i][j],
@@ -1028,11 +1052,17 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
prim_type.reserve(reserve);
prim_index.reserve(reserve);
prim_object.reserve(reserve);
+ if(need_prim_time) {
+ prim_time.reserve(reserve);
+ }
}
prim_type.resize(range_end);
prim_index.resize(range_end);
prim_object.resize(range_end);
+ if(need_prim_time) {
+ prim_time.resize(range_end);
+ }
}
spatial_spin_lock.unlock();
@@ -1041,6 +1071,9 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
memcpy(&prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
memcpy(&prim_index[start_index], &local_prim_index[0], new_leaf_data_size);
memcpy(&prim_object[start_index], &local_prim_object[0], new_leaf_data_size);
+ if(need_prim_time) {
+ memcpy(&prim_time[start_index], &local_prim_time[0], sizeof(float2)*num_new_leaf_data);
+ }
}
}
else {
@@ -1053,6 +1086,9 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
memcpy(&prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
memcpy(&prim_index[start_index], &local_prim_index[0], new_leaf_data_size);
memcpy(&prim_object[start_index], &local_prim_object[0], new_leaf_data_size);
+ if(need_prim_time) {
+ memcpy(&prim_time[start_index], &local_prim_time[0], sizeof(float2)*num_new_leaf_data);
+ }
}
}
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index ee3cde66a2f..430efc3e0f6 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -48,6 +48,7 @@ public:
array<int>& prim_type,
array<int>& prim_index,
array<int>& prim_object,
+ array<float2>& prim_time,
const BVHParams& params,
Progress& progress);
~BVHBuild();
@@ -112,6 +113,9 @@ protected:
array<int>& prim_type;
array<int>& prim_index;
array<int>& prim_object;
+ array<float2>& prim_time;
+
+ bool need_prim_time;
/* Build parameters. */
BVHParams params;
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index 65f9da1c194..7b309504728 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -104,6 +104,7 @@ public:
primitive_mask = PRIMITIVE_ALL;
num_motion_curve_steps = 0;
+ num_motion_triangle_steps = 0;
}
/* SAH costs */
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h
index 36798982653..321983c1abc 100644
--- a/intern/cycles/kernel/bvh/bvh.h
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -357,7 +357,7 @@ ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
#endif
}
-#if defined(__SHADOW_RECORD_ALL__) || defined (__VOLUME_RECORD_ALL__)
+#if defined(__VOLUME_RECORD_ALL__) || (defined(__SHADOW_RECORD_ALL__) && defined(__KERNEL_CPU__))
/* ToDo: Move to another file? */
ccl_device int intersections_compare(const void *a, const void *b)
{
@@ -373,5 +373,28 @@ ccl_device int intersections_compare(const void *a, const void *b)
}
#endif
-CCL_NAMESPACE_END
+#if defined(__SHADOW_RECORD_ALL__)
+ccl_device_inline void sort_intersections(Intersection *hits, uint num_hits)
+{
+#ifdef __KERNEL_GPU__
+ /* Use bubble sort which has more friendly memory pattern on GPU. */
+ bool swapped;
+ do {
+ swapped = false;
+ for(int j = 0; j < num_hits - 1; ++j) {
+ if(hits[j].t > hits[j + 1].t) {
+ struct Intersection tmp = hits[j];
+ hits[j] = hits[j + 1];
+ hits[j + 1] = tmp;
+ swapped = true;
+ }
+ }
+ --num_hits;
+ } while(swapped);
+#else
+ qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
+#endif
+}
+#endif /* __SHADOW_RECORD_ALL__ | __VOLUME_RECORD_ALL__ */
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index 9de335403ce..712b67a1b55 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -229,6 +229,15 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte
float3 P, float3 dir, uint visibility, int object, int curveAddr, float time,int type, uint *lcg_state, float difl, float extmax)
#endif
{
+ const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
+
+ if(!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
+ const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
+ if(time < prim_time.x || time > prim_time.y) {
+ return false;
+ }
+ }
+
int segment = PRIMITIVE_UNPACK_SEGMENT(type);
float epsilon = 0.0f;
float r_st, r_en;
@@ -257,7 +266,7 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte
#ifdef __KERNEL_AVX2__
avxf P_curve_0_1, P_curve_2_3;
- if(type & PRIMITIVE_CURVE) {
+ if(is_curve_primitive) {
P_curve_0_1 = _mm256_loadu2_m128(&kg->__curve_keys.data[k0].x, &kg->__curve_keys.data[ka].x);
P_curve_2_3 = _mm256_loadu2_m128(&kg->__curve_keys.data[kb].x, &kg->__curve_keys.data[k1].x);
}
@@ -268,7 +277,7 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte
#else /* __KERNEL_AVX2__ */
ssef P_curve[4];
- if(type & PRIMITIVE_CURVE) {
+ if(is_curve_primitive) {
P_curve[0] = load4f(&kg->__curve_keys.data[ka].x);
P_curve[1] = load4f(&kg->__curve_keys.data[k0].x);
P_curve[2] = load4f(&kg->__curve_keys.data[k1].x);
@@ -363,7 +372,7 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte
float4 P_curve[4];
- if(type & PRIMITIVE_CURVE) {
+ if(is_curve_primitive) {
P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
@@ -689,6 +698,15 @@ ccl_device_forceinline bool bvh_curve_intersect(KernelGlobals *kg, Intersection
# define dot3(x, y) dot(x, y)
#endif
+ const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
+
+ if(!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
+ const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
+ if(time < prim_time.x || time > prim_time.y) {
+ return false;
+ }
+ }
+
int segment = PRIMITIVE_UNPACK_SEGMENT(type);
/* curve Intersection check */
int flags = kernel_data.curve.curveflags;
@@ -703,7 +721,7 @@ ccl_device_forceinline bool bvh_curve_intersect(KernelGlobals *kg, Intersection
#ifndef __KERNEL_SSE2__
float4 P_curve[2];
- if(type & PRIMITIVE_CURVE) {
+ if(is_curve_primitive) {
P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
}
@@ -738,7 +756,7 @@ ccl_device_forceinline bool bvh_curve_intersect(KernelGlobals *kg, Intersection
#else
ssef P_curve[2];
- if(type & PRIMITIVE_CURVE) {
+ if(is_curve_primitive) {
P_curve[0] = load4f(&kg->__curve_keys.data[k0].x);
P_curve[1] = load4f(&kg->__curve_keys.data[k1].x);
}
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index a0ee4970613..5dbea4481a3 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -83,7 +83,10 @@ typedef struct KernelGlobals {
#ifdef __KERNEL_CUDA__
__constant__ KernelData __data;
-typedef struct KernelGlobals {} KernelGlobals;
+typedef struct KernelGlobals {
+ /* NOTE: Keep the size in sync with SHADOW_STACK_MAX_HITS. */
+ Intersection hits_stack[64];
+} KernelGlobals;
# ifdef __KERNEL_CUDA_TEX_STORAGE__
# define KERNEL_TEX(type, ttype, name) ttype name;
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index 84b5fd254ca..6abfa9c3873 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -16,9 +16,84 @@
CCL_NAMESPACE_BEGIN
-#ifdef __SHADOW_RECORD_ALL__
+/* Attenuate throughput accordingly to the given intersection event.
+ * Returns true if the throughput is zero and traversal can be aborted.
+ */
+ccl_device_forceinline bool shadow_handle_transparent_isect(
+ KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+# ifdef __VOLUME__
+ struct PathState *volume_state,
+# endif
+ Intersection *isect,
+ Ray *ray,
+ float3 *throughput)
+{
+#ifdef __VOLUME__
+ /* Attenuation between last surface and next surface. */
+ if(volume_state->volume_stack[0].shader != SHADER_NONE) {
+ Ray segment_ray = *ray;
+ segment_ray.t = isect->t;
+ kernel_volume_shadow(kg,
+ shadow_sd,
+ volume_state,
+ &segment_ray,
+ throughput);
+ }
+#endif
+ /* Setup shader data at surface. */
+ shader_setup_from_ray(kg, shadow_sd, isect, ray);
+ /* Attenuation from transparent surface. */
+ if(!(ccl_fetch(shadow_sd, flag) & SD_HAS_ONLY_VOLUME)) {
+ path_state_modify_bounce(state, true);
+ shader_eval_surface(kg,
+ shadow_sd,
+ NULL,
+ state,
+ 0.0f,
+ PATH_RAY_SHADOW,
+ SHADER_CONTEXT_SHADOW);
+ path_state_modify_bounce(state, false);
+ *throughput *= shader_bsdf_transparency(kg, shadow_sd);
+ }
+ /* Stop if all light is blocked. */
+ if(is_zero(*throughput)) {
+ return true;
+ }
+#ifdef __VOLUME__
+ /* Exit/enter volume. */
+ kernel_volume_stack_enter_exit(kg, shadow_sd, volume_state->volume_stack);
+#endif
+ return false;
+}
+
+/* Special version which only handles opaque shadows. */
+ccl_device bool shadow_blocked_opaque(KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ Intersection *isect,
+ float3 *shadow)
+{
+ const bool blocked = scene_intersect(kg,
+ *ray,
+ PATH_RAY_SHADOW_OPAQUE,
+ isect,
+ NULL,
+ 0.0f, 0.0f);
+#ifdef __VOLUME__
+ if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
+ /* Apply attenuation from current volume shader. */
+ kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
+ }
+#endif
+ return blocked;
+}
-/* Shadow function to compute how much light is blocked, CPU variation.
+#ifdef __TRANSPARENT_SHADOWS__
+# ifdef __SHADOW_RECORD_ALL__
+/* Shadow function to compute how much light is blocked,
*
* We trace a single ray. If it hits any opaque surface, or more than a given
* number of transparent surfaces is hit, then we consider the geometry to be
@@ -36,261 +111,355 @@ CCL_NAMESPACE_BEGIN
* or there is a performance increase anyway due to avoiding the need to send
* two rays with transparent shadows.
*
- * This is CPU only because of qsort, and malloc or high stack space usage to
- * record all these intersections. */
+ * On CPU it'll handle all transparent bounces (by allocating storage for
+ * intersections when they don't fit into the stack storage).
+ *
+ * On GPU it'll only handle SHADOW_STACK_MAX_HITS-1 intersections, so this
+ * is something to be kept an eye on.
+ */
-#define STACK_MAX_HITS 64
+# define SHADOW_STACK_MAX_HITS 64
-ccl_device_inline bool shadow_blocked(KernelGlobals *kg, ShaderData *shadow_sd, PathState *state, Ray *ray, float3 *shadow)
+/* Actual logic with traversal loop implementation which is free from device
+ * specific tweaks.
+ *
+ * Note that hits array should be as big as max_hits+1.
+ */
+ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ Intersection *hits,
+ uint max_hits,
+ float3 *shadow)
{
- *shadow = make_float3(1.0f, 1.0f, 1.0f);
-
- if(ray->t == 0.0f)
- return false;
-
- bool blocked;
-
- if(kernel_data.integrator.transparent_shadows) {
- /* check transparent bounces here, for volume scatter which can do
- * lighting before surface path termination is checked */
- if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce)
- return true;
-
- /* intersect to find an opaque surface, or record all transparent surface hits */
- Intersection hits_stack[STACK_MAX_HITS];
- Intersection *hits = hits_stack;
- const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
- uint max_hits = transparent_max_bounce - state->transparent_bounce - 1;
-
- /* prefer to use stack but use dynamic allocation if too deep max hits
- * we need max_hits + 1 storage space due to the logic in
- * scene_intersect_shadow_all which will first store and then check if
- * the limit is exceeded */
- if(max_hits + 1 > STACK_MAX_HITS) {
- if(kg->transparent_shadow_intersections == NULL) {
- kg->transparent_shadow_intersections =
- (Intersection*)malloc(sizeof(Intersection)*(transparent_max_bounce + 1));
+ /* Intersect to find an opaque surface, or record all transparent
+ * surface hits.
+ */
+ uint num_hits;
+ const bool blocked = scene_intersect_shadow_all(kg,
+ ray,
+ hits,
+ max_hits,
+ &num_hits);
+ /* If no opaque surface found but we did find transparent hits,
+ * shade them.
+ */
+ if(!blocked && num_hits > 0) {
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 Pend = ray->P + ray->D*ray->t;
+ float last_t = 0.0f;
+ int bounce = state->transparent_bounce;
+ Intersection *isect = hits;
+# ifdef __VOLUME__
+ PathState ps = *state;
+# endif
+ sort_intersections(hits, num_hits);
+ for(int hit = 0; hit < num_hits; hit++, isect++) {
+ /* Adjust intersection distance for moving ray forward. */
+ float new_t = isect->t;
+ isect->t -= last_t;
+ /* Skip hit if we did not move forward, step by step raytracing
+ * would have skipped it as well then.
+ */
+ if(last_t == new_t) {
+ continue;
}
- hits = kg->transparent_shadow_intersections;
- }
-
- uint num_hits;
- blocked = scene_intersect_shadow_all(kg, ray, hits, max_hits, &num_hits);
-
- /* if no opaque surface found but we did find transparent hits, shade them */
- if(!blocked && num_hits > 0) {
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float3 Pend = ray->P + ray->D*ray->t;
- float last_t = 0.0f;
- int bounce = state->transparent_bounce;
- Intersection *isect = hits;
+ last_t = new_t;
+ /* Attenuate the throughput. */
+ if(shadow_handle_transparent_isect(kg,
+ shadow_sd,
+ state,
#ifdef __VOLUME__
- PathState ps = *state;
+ &ps,
#endif
-
- qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
-
- for(int hit = 0; hit < num_hits; hit++, isect++) {
- /* adjust intersection distance for moving ray forward */
- float new_t = isect->t;
- isect->t -= last_t;
-
- /* skip hit if we did not move forward, step by step raytracing
- * would have skipped it as well then */
- if(last_t == new_t)
- continue;
-
- last_t = new_t;
-
-#ifdef __VOLUME__
- /* attenuation between last surface and next surface */
- if(ps.volume_stack[0].shader != SHADER_NONE) {
- Ray segment_ray = *ray;
- segment_ray.t = isect->t;
- kernel_volume_shadow(kg, shadow_sd, &ps, &segment_ray, &throughput);
- }
-#endif
-
- /* setup shader data at surface */
- shader_setup_from_ray(kg, shadow_sd, isect, ray);
-
- /* attenuation from transparent surface */
- if(!(shadow_sd->flag & SD_HAS_ONLY_VOLUME)) {
- path_state_modify_bounce(state, true);
- shader_eval_surface(kg, shadow_sd, NULL, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
- path_state_modify_bounce(state, false);
-
- throughput *= shader_bsdf_transparency(kg, shadow_sd);
- }
-
- /* stop if all light is blocked */
- if(is_zero(throughput)) {
- return true;
- }
-
- /* move ray forward */
- ray->P = shadow_sd->P;
- if(ray->t != FLT_MAX) {
- ray->D = normalize_len(Pend - ray->P, &ray->t);
- }
-
-#ifdef __VOLUME__
- /* exit/enter volume */
- kernel_volume_stack_enter_exit(kg, shadow_sd, ps.volume_stack);
-#endif
-
- bounce++;
+ isect,
+ ray,
+ &throughput))
+ {
+ return true;
}
-
-#ifdef __VOLUME__
- /* attenuation for last line segment towards light */
- if(ps.volume_stack[0].shader != SHADER_NONE)
- kernel_volume_shadow(kg, shadow_sd, &ps, ray, &throughput);
-#endif
-
- *shadow = throughput;
-
- return is_zero(throughput);
+ /* Move ray forward. */
+ ray->P = ccl_fetch(shadow_sd, P);
+ if(ray->t != FLT_MAX) {
+ ray->D = normalize_len(Pend - ray->P, &ray->t);
+ }
+ bounce++;
}
+# ifdef __VOLUME__
+ /* Attenuation for last line segment towards light. */
+ if(ps.volume_stack[0].shader != SHADER_NONE) {
+ kernel_volume_shadow(kg, shadow_sd, &ps, ray, &throughput);
+ }
+# endif
+ *shadow = throughput;
+ return is_zero(throughput);
}
- else {
- Intersection isect;
- blocked = scene_intersect(kg, *ray, PATH_RAY_SHADOW_OPAQUE, &isect, NULL, 0.0f, 0.0f);
- }
-
-#ifdef __VOLUME__
+# ifdef __VOLUME__
if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
- /* apply attenuation from current volume shader */
+ /* Apply attenuation from current volume shader/ */
kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
}
-#endif
-
+# endif
return blocked;
}
-#undef STACK_MAX_HITS
-
-#else
+/* Here we do all device specific trickery before invoking actual traversal
+ * loop to help readability of the actual logic.
+ */
+ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ uint max_hits,
+ float3 *shadow)
+{
+# ifdef __KERNEL_CUDA__
+ Intersection *hits = kg->hits_stack;
+# else
+ Intersection hits_stack[SHADOW_STACK_MAX_HITS];
+ Intersection *hits = hits_stack;
+# endif
+# ifndef __KERNEL_GPU__
+ /* Prefer to use stack but use dynamic allocation if too deep max hits
+ * we need max_hits + 1 storage space due to the logic in
+ * scene_intersect_shadow_all which will first store and then check if
+ * the limit is exceeded.
+ *
+ * Ignore this on GPU because of slow/unavailable malloc().
+ */
+ if(max_hits + 1 > SHADOW_STACK_MAX_HITS) {
+ if(kg->transparent_shadow_intersections == NULL) {
+ const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
+ kg->transparent_shadow_intersections =
+ (Intersection*)malloc(sizeof(Intersection)*(transparent_max_bounce + 1));
+ }
+ hits = kg->transparent_shadow_intersections;
+ }
+# endif /* __KERNEL_GPU__ */
+ /* Invoke actual traversal. */
+ return shadow_blocked_transparent_all_loop(kg,
+ shadow_sd,
+ state,
+ ray,
+ hits,
+ max_hits,
+ shadow);
+}
+# endif /* __SHADOW_RECORD_ALL__ */
-/* Shadow function to compute how much light is blocked, GPU variation.
+# if defined(__KERNEL_GPU__) || !defined(__SHADOW_RECORD_ALL__)
+/* Shadow function to compute how much light is blocked,
*
* Here we raytrace from one transparent surface to the next step by step.
* To minimize overhead in cases where we don't need transparent shadows, we
* first trace a regular shadow ray. We check if the hit primitive was
* potentially transparent, and only in that case start marching. this gives
- * one extra ray cast for the cases were we do want transparency. */
+ * one extra ray cast for the cases were we do want transparency.
+ */
-ccl_device_noinline bool shadow_blocked(KernelGlobals *kg,
- ShaderData *shadow_sd,
- ccl_addr_space PathState *state,
- ccl_addr_space Ray *ray_input,
- float3 *shadow)
+/* This function is only implementing device-independent traversal logic
+ * which requires some precalculation done.
+ */
+ccl_device bool shadow_blocked_transparent_stepped_loop(
+ KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ Intersection *isect,
+ const bool blocked,
+ const bool is_transparent_isect,
+ float3 *shadow)
{
- *shadow = make_float3(1.0f, 1.0f, 1.0f);
+ if(blocked && is_transparent_isect) {
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 Pend = ray->P + ray->D*ray->t;
+ int bounce = state->transparent_bounce;
+# ifdef __VOLUME__
+ PathState ps = *state;
+# endif
+ for(;;) {
+ if(bounce >= kernel_data.integrator.transparent_max_bounce) {
+ return true;
+ }
+ if(!scene_intersect(kg,
+ *ray,
+ PATH_RAY_SHADOW_TRANSPARENT,
+ isect,
+ NULL,
+ 0.0f, 0.0f))
+ {
+ break;
+ }
+ if(!shader_transparent_shadow(kg, isect)) {
+ return true;
+ }
+ /* Attenuate the throughput. */
+ if(shadow_handle_transparent_isect(kg,
+ shadow_sd,
+ state,
+#ifdef __VOLUME__
+ &ps,
+#endif
+ isect,
+ ray,
+ &throughput))
+ {
+ return true;
+ }
+ /* Move ray forward. */
+ ray->P = ray_offset(ccl_fetch(shadow_sd, P), -ccl_fetch(shadow_sd, Ng));
+ if(ray->t != FLT_MAX) {
+ ray->D = normalize_len(Pend - ray->P, &ray->t);
+ }
+ bounce++;
+ }
+# ifdef __VOLUME__
+ /* Attenuation for last line segment towards light. */
+ if(ps.volume_stack[0].shader != SHADER_NONE) {
+ kernel_volume_shadow(kg, shadow_sd, &ps, ray, &throughput);
+ }
+# endif
+ *shadow *= throughput;
+ return is_zero(throughput);
+ }
+# ifdef __VOLUME__
+ if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
+ /* Apply attenuation from current volume shader. */
+ kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
+ }
+# endif
+ return blocked;
+}
- if(ray_input->t == 0.0f)
- return false;
+ccl_device bool shadow_blocked_transparent_stepped(
+ KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ Intersection *isect,
+ float3 *shadow)
+{
+ const bool blocked = scene_intersect(kg,
+ *ray,
+ PATH_RAY_SHADOW_OPAQUE,
+ isect,
+ NULL,
+ 0.0f, 0.0f);
+ const bool is_transparent_isect = blocked
+ ? shader_transparent_shadow(kg, isect)
+ : false;
+ return shadow_blocked_transparent_stepped_loop(kg,
+ shadow_sd,
+ state,
+ ray,
+ isect,
+ blocked,
+ is_transparent_isect,
+ shadow);
+}
+# endif /* __KERNEL_GPU__ || !__SHADOW_RECORD_ALL__ */
+#endif /* __TRANSPARENT_SHADOWS__ */
+
+ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ ccl_addr_space Ray *ray_input,
+ float3 *shadow)
+{
+ /* Special trickery for split kernel: some data is coming from the
+ * global memory.
+ */
#ifdef __SPLIT_KERNEL__
Ray private_ray = *ray_input;
Ray *ray = &private_ray;
-#else
- Ray *ray = ray_input;
-#endif
-
-#ifdef __SPLIT_KERNEL__
Intersection *isect = &kernel_split_state.isect_shadow[SD_THREAD];
-#else
+#else /* __SPLIT_KERNEL__ */
+ Ray *ray = ray_input;
Intersection isect_object;
Intersection *isect = &isect_object;
-#endif
-
- bool blocked = scene_intersect(kg, *ray, PATH_RAY_SHADOW_OPAQUE, isect, NULL, 0.0f, 0.0f);
-
+#endif /* __SPLIT_KERNEL__ */
+ /* Some common early checks. */
+ *shadow = make_float3(1.0f, 1.0f, 1.0f);
+ if(ray->t == 0.0f) {
+ return false;
+ }
+ /* Do actual shadow shading. */
+ /* First of all, we check if integrator requires transparent shadows.
+ * if not, we use simplest and fastest ever way to calculate occlusion.
+ */
#ifdef __TRANSPARENT_SHADOWS__
- if(blocked && kernel_data.integrator.transparent_shadows) {
- if(shader_transparent_shadow(kg, isect)) {
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float3 Pend = ray->P + ray->D*ray->t;
- int bounce = state->transparent_bounce;
-#ifdef __VOLUME__
- PathState ps = *state;
+ if(!kernel_data.integrator.transparent_shadows)
#endif
-
- for(;;) {
- if(bounce >= kernel_data.integrator.transparent_max_bounce)
- return true;
-
- if(!scene_intersect(kg, *ray, PATH_RAY_SHADOW_TRANSPARENT, isect, NULL, 0.0f, 0.0f))
- {
-#ifdef __VOLUME__
- /* attenuation for last line segment towards light */
- if(ps.volume_stack[0].shader != SHADER_NONE)
- kernel_volume_shadow(kg, shadow_sd, &ps, ray, &throughput);
-#endif
-
- *shadow *= throughput;
-
- return false;
- }
-
- if(!shader_transparent_shadow(kg, isect)) {
- return true;
- }
-
-#ifdef __VOLUME__
- /* attenuation between last surface and next surface */
- if(ps.volume_stack[0].shader != SHADER_NONE) {
- Ray segment_ray = *ray;
- segment_ray.t = isect->t;
- kernel_volume_shadow(kg, shadow_sd, &ps, &segment_ray, &throughput);
- }
-#endif
-
- /* setup shader data at surface */
- shader_setup_from_ray(kg, shadow_sd, isect, ray);
-
- /* attenuation from transparent surface */
- if(!(ccl_fetch(shadow_sd, flag) & SD_HAS_ONLY_VOLUME)) {
- path_state_modify_bounce(state, true);
- shader_eval_surface(kg, shadow_sd, NULL, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
- path_state_modify_bounce(state, false);
-
- throughput *= shader_bsdf_transparency(kg, shadow_sd);
- }
-
- /* stop if all light is blocked */
- if(is_zero(throughput)) {
- return true;
- }
-
- /* move ray forward */
- ray->P = ray_offset(ccl_fetch(shadow_sd, P), -ccl_fetch(shadow_sd, Ng));
- if(ray->t != FLT_MAX) {
- ray->D = normalize_len(Pend - ray->P, &ray->t);
- }
-
-#ifdef __VOLUME__
- /* exit/enter volume */
- kernel_volume_stack_enter_exit(kg, shadow_sd, ps.volume_stack);
-#endif
-
- bounce++;
- }
- }
+ {
+ return shadow_blocked_opaque(kg,
+ shadow_sd,
+ state,
+ ray,
+ isect,
+ shadow);
}
-#ifdef __VOLUME__
- else if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
- /* apply attenuation from current volume shader */
- kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
+#ifdef __TRANSPARENT_SHADOWS__
+# ifdef __SHADOW_RECORD_ALL__
+ /* For the transparent shadows we try to use record-all logic on the
+ * devices which supports this.
+ */
+ const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
+ /* Check transparent bounces here, for volume scatter which can do
+ * lighting before surface path termination is checked.
+ */
+ if(state->transparent_bounce >= transparent_max_bounce) {
+ return true;
}
-#endif
-#endif
-
- return blocked;
+ const uint max_hits = transparent_max_bounce - state->transparent_bounce - 1;
+# ifdef __KERNEL_GPU__
+ /* On GPU we do trickey with tracing opaque ray first, this avoids speed
+ * regressions in some files.
+ *
+ * TODO(sergey): Check why using record-all behavior causes slowdown in such
+ * cases. Could that be caused by a higher spill pressure?
+ */
+ const bool blocked = scene_intersect(kg,
+ *ray,
+ PATH_RAY_SHADOW_OPAQUE,
+ isect,
+ NULL,
+ 0.0f, 0.0f);
+ const bool is_transparent_isect = blocked
+ ? shader_transparent_shadow(kg, isect)
+ : false;
+ if(!blocked || !is_transparent_isect ||
+ max_hits + 1 >= SHADOW_STACK_MAX_HITS)
+ {
+ return shadow_blocked_transparent_stepped_loop(kg,
+ shadow_sd,
+ state,
+ ray,
+ isect,
+ blocked,
+ is_transparent_isect,
+ shadow);
+ }
+# endif /* __KERNEL_GPU__ */
+ return shadow_blocked_transparent_all(kg,
+ shadow_sd,
+ state,
+ ray,
+ max_hits,
+ shadow);
+# else /* __SHADOW_RECORD_ALL__ */
+ /* Fallback to a slowest version which works on all devices. */
+ return shadow_blocked_transparent_stepped(kg,
+ shadow_sd,
+ state,
+ ray,
+ isect,
+ shadow);
+# endif /* __SHADOW_RECORD_ALL__ */
+#endif /* __TRANSPARENT_SHADOWS__ */
}
-#endif
+#undef SHADOW_STACK_MAX_HITS
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 8d5bb75a428..cb1a3f40dee 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -32,6 +32,7 @@ KERNEL_TEX(uint, texture_uint, __prim_visibility)
KERNEL_TEX(uint, texture_uint, __prim_index)
KERNEL_TEX(uint, texture_uint, __prim_object)
KERNEL_TEX(uint, texture_uint, __object_node)
+KERNEL_TEX(float2, texture_float2, __prim_time)
/* objects */
KERNEL_TEX(float4, texture_float4, __objects)
@@ -177,7 +178,6 @@ KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_085)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_086)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_087)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_088)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_089)
# else
/* bindless textures */
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index b69cec21400..070933fdfd1 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -98,6 +98,7 @@ CCL_NAMESPACE_BEGIN
# define __VOLUME_SCATTER__
# define __SUBSURFACE__
# define __CMJ__
+# define __SHADOW_RECORD_ALL__
# endif
#endif /* __KERNEL_CUDA__ */
@@ -1218,7 +1219,8 @@ typedef struct KernelBVH {
int have_curves;
int have_instancing;
int use_qbvh;
- int pad1, pad2;
+ int use_bvh_steps;
+ int pad1;
} KernelBVH;
static_assert_align(KernelBVH, 16);
diff --git a/intern/cycles/kernel/kernels/cuda/kernel.cu b/intern/cycles/kernel/kernels/cuda/kernel.cu
index bfa852235fc..52e541321e3 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel.cu
+++ b/intern/cycles/kernel/kernels/cuda/kernel.cu
@@ -36,8 +36,10 @@ kernel_cuda_path_trace(float *buffer, uint *rng_state, int sample, int sx, int s
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
- if(x < sx + sw && y < sy + sh)
- kernel_path_trace(NULL, buffer, rng_state, sample, x, y, offset, stride);
+ if(x < sx + sw && y < sy + sh) {
+ KernelGlobals kg;
+ kernel_path_trace(&kg, buffer, rng_state, sample, x, y, offset, stride);
+ }
}
#ifdef __BRANCHED_PATH__
@@ -48,8 +50,10 @@ kernel_cuda_branched_path_trace(float *buffer, uint *rng_state, int sample, int
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
- if(x < sx + sw && y < sy + sh)
- kernel_branched_path_trace(NULL, buffer, rng_state, sample, x, y, offset, stride);
+ if(x < sx + sw && y < sy + sh) {
+ KernelGlobals kg;
+ kernel_branched_path_trace(&kg, buffer, rng_state, sample, x, y, offset, stride);
+ }
}
#endif
@@ -60,8 +64,9 @@ kernel_cuda_convert_to_byte(uchar4 *rgba, float *buffer, float sample_scale, int
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
- if(x < sx + sw && y < sy + sh)
+ if(x < sx + sw && y < sy + sh) {
kernel_film_convert_to_byte(NULL, rgba, buffer, sample_scale, x, y, offset, stride);
+ }
}
extern "C" __global__ void
@@ -71,8 +76,9 @@ kernel_cuda_convert_to_half_float(uchar4 *rgba, float *buffer, float sample_scal
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
- if(x < sx + sw && y < sy + sh)
+ if(x < sx + sw && y < sy + sh) {
kernel_film_convert_to_half_float(NULL, rgba, buffer, sample_scale, x, y, offset, stride);
+ }
}
extern "C" __global__ void
@@ -89,7 +95,8 @@ kernel_cuda_shader(uint4 *input,
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
if(x < sx + sw) {
- kernel_shader_evaluate(NULL,
+ KernelGlobals kg;
+ kernel_shader_evaluate(&kg,
input,
output,
output_luma,
@@ -106,8 +113,10 @@ kernel_cuda_bake(uint4 *input, float4 *output, int type, int filter, int sx, int
{
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
- if(x < sx + sw)
- kernel_bake_evaluate(NULL, input, output, (ShaderEvalType)type, filter, x, offset, sample);
+ if(x < sx + sw) {
+ KernelGlobals kg;
+ kernel_bake_evaluate(&kg, input, output, (ShaderEvalType)type, filter, x, offset, sample);
+ }
}
#endif
diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index 2afdf61b476..0d6efb47223 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -144,7 +144,6 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
case 86: r = kernel_tex_image_interp(__tex_image_byte4_086, x, y); break;
case 87: r = kernel_tex_image_interp(__tex_image_byte4_087, x, y); break;
case 88: r = kernel_tex_image_interp(__tex_image_byte4_088, x, y); break;
- case 89: r = kernel_tex_image_interp(__tex_image_byte4_089, x, y); break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/svm/svm_math_util.h b/intern/cycles/kernel/svm/svm_math_util.h
index 01547b60014..a7f15de7325 100644
--- a/intern/cycles/kernel/svm/svm_math_util.h
+++ b/intern/cycles/kernel/svm/svm_math_util.h
@@ -134,32 +134,37 @@ ccl_device float3 svm_math_blackbody_color(float t) {
{ 6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f },
};
- if(t >= 12000.0f)
+ int i;
+ if(t >= 12000.0f) {
return make_float3(0.826270103f, 0.994478524f, 1.56626022f);
+ }
+ else if(t >= 6365.0f) {
+ i = 5;
+ }
+ else if(t >= 3315.0f) {
+ i = 4;
+ }
+ else if(t >= 1902.0f) {
+ i = 3;
+ }
+ else if(t >= 1449.0f) {
+ i = 2;
+ }
+ else if(t >= 1167.0f) {
+ i = 1;
+ }
+ else if(t >= 965.0f) {
+ i = 0;
+ }
+ else {
+ /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */
+ return make_float3(4.70366907f, 0.0f, 0.0f);
+ }
- /* Define a macro to reduce stack usage for nvcc */
-#define MAKE_BB_RGB(i) make_float3(\
- rc[i][0] / t + rc[i][1] * t + rc[i][2],\
- gc[i][0] / t + gc[i][1] * t + gc[i][2],\
- ((bc[i][0] * t + bc[i][1]) * t + bc[i][2]) * t + bc[i][3])
-
- if(t >= 6365.0f)
- return MAKE_BB_RGB(5);
- if(t >= 3315.0f)
- return MAKE_BB_RGB(4);
- if(t >= 1902.0f)
- return MAKE_BB_RGB(3);
- if(t >= 1449.0f)
- return MAKE_BB_RGB(2);
- if(t >= 1167.0f)
- return MAKE_BB_RGB(1);
- if(t >= 965.0f)
- return MAKE_BB_RGB(0);
-
-#undef MAKE_BB_RGB
-
- /* For 800 <= t < 965 color does not change in OSL implementation, so keep color the same */
- return make_float3(4.70366907f, 0.0f, 0.0f);
+ const float t_inv = 1.0f / t;
+ return make_float3(rc[i][0] * t_inv + rc[i][1] * t + rc[i][2],
+ gc[i][0] * t_inv + gc[i][1] * t + gc[i][2],
+ ((bc[i][0] * t + bc[i][1]) * t + bc[i][2]) * t + bc[i][3]);
}
ccl_device_inline float3 svm_math_gamma_color(float3 color, float gamma)
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
index 25f5eb3c897..aed9c5a8e75 100644
--- a/intern/cycles/render/bake.h
+++ b/intern/cycles/render/bake.h
@@ -73,7 +73,7 @@ public:
bool need_update;
- int total_pixel_samples;
+ size_t total_pixel_samples;
private:
BakeData *m_bake_data;
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 473bf776abf..fc6790dc022 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -486,10 +486,18 @@ static void background_cdf(int start,
float2 *cond_cdf)
{
/* Conditional CDFs (rows, U direction). */
+ /* NOTE: It is possible to have some NaN pixels on background
+ * which will ruin CDF causing wrong shading. We replace such
+ * pixels with black.
+ */
for(int i = start; i < end; i++) {
float sin_theta = sinf(M_PI_F * (i + 0.5f) / res);
float3 env_color = (*pixels)[i * res];
float ave_luminance = average(env_color);
+ /* TODO(sergey): Consider adding average_safe(). */
+ if(!isfinite(ave_luminance)) {
+ ave_luminance = 0.0f;
+ }
cond_cdf[i * cdf_count].x = ave_luminance * sin_theta;
cond_cdf[i * cdf_count].y = 0.0f;
@@ -497,6 +505,9 @@ static void background_cdf(int start,
for(int j = 1; j < res; j++) {
env_color = (*pixels)[i * res + j];
ave_luminance = average(env_color);
+ if(!isfinite(ave_luminance)) {
+ ave_luminance = 0.0f;
+ }
cond_cdf[i * cdf_count + j].x = ave_luminance * sin_theta;
cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res;
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index c42b32919d4..b7660297f3e 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -1873,9 +1873,14 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->prim_object.reference((uint*)&pack.prim_object[0], pack.prim_object.size());
device->tex_alloc("__prim_object", dscene->prim_object);
}
+ if(pack.prim_time.size()) {
+ dscene->prim_time.reference((float2*)&pack.prim_time[0], pack.prim_time.size());
+ device->tex_alloc("__prim_time", dscene->prim_time);
+ }
dscene->data.bvh.root = pack.root_index;
dscene->data.bvh.use_qbvh = scene->params.use_qbvh;
+ dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
}
void MeshManager::device_update_flags(Device * /*device*/,
@@ -2152,6 +2157,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->prim_visibility);
device->tex_free(dscene->prim_index);
device->tex_free(dscene->prim_object);
+ device->tex_free(dscene->prim_time);
device->tex_free(dscene->tri_shader);
device->tex_free(dscene->tri_vnormal);
device->tex_free(dscene->tri_vindex);
@@ -2173,6 +2179,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
dscene->prim_visibility.clear();
dscene->prim_index.clear();
dscene->prim_object.clear();
+ dscene->prim_time.clear();
dscene->tri_shader.clear();
dscene->tri_vnormal.clear();
dscene->tri_vindex.clear();
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 8768682043f..9f398c444f4 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -69,6 +69,7 @@ public:
device_vector<uint> prim_visibility;
device_vector<uint> prim_index;
device_vector<uint> prim_object;
+ device_vector<float2> prim_time;
/* mesh */
device_vector<uint> tri_shader;
diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp
index 32b4c7265ee..3fc086cbc0c 100644
--- a/intern/cycles/test/render_graph_finalize_test.cpp
+++ b/intern/cycles/test/render_graph_finalize_test.cpp
@@ -92,7 +92,7 @@ public:
template<typename T>
ShaderGraphBuilder& add_node(const T& node)
{
- EXPECT_EQ(NULL, find_node(node.name()));
+ EXPECT_EQ(find_node(node.name()), (void*)NULL);
graph_->add(node.node());
node_map_[node.name()] = node.node();
return *this;
@@ -104,8 +104,8 @@ public:
vector<string> tokens_from, tokens_to;
string_split(tokens_from, from, "::");
string_split(tokens_to, to, "::");
- EXPECT_EQ(2, tokens_from.size());
- EXPECT_EQ(2, tokens_to.size());
+ EXPECT_EQ(tokens_from.size(), 2);
+ EXPECT_EQ(tokens_to.size(), 2);
ShaderNode *node_from = find_node(tokens_from[0]),
*node_to = find_node(tokens_to[0]);
EXPECT_NE((void*)NULL, node_from);
diff --git a/intern/cycles/test/util_aligned_malloc_test.cpp b/intern/cycles/test/util_aligned_malloc_test.cpp
index 479070f0513..9fb3aad0c3f 100644
--- a/intern/cycles/test/util_aligned_malloc_test.cpp
+++ b/intern/cycles/test/util_aligned_malloc_test.cpp
@@ -18,7 +18,7 @@
#include "util/util_aligned_malloc.h"
-#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ(0, (size_t)ptr % align)
+#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ((size_t)ptr % align, 0)
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/test/util_path_test.cpp b/intern/cycles/test/util_path_test.cpp
index 92be1dd4cbe..c2f400c105d 100644
--- a/intern/cycles/test/util_path_test.cpp
+++ b/intern/cycles/test/util_path_test.cpp
@@ -26,63 +26,63 @@ CCL_NAMESPACE_BEGIN
TEST(util_path_filename, simple_unix)
{
string str = path_filename("/tmp/foo.txt");
- EXPECT_EQ("foo.txt", str);
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_filename, root_unix)
{
string str = path_filename("/");
- EXPECT_EQ("/", str);
+ EXPECT_EQ(str, "/");
}
TEST(util_path_filename, last_slash_unix)
{
string str = path_filename("/tmp/foo.txt/");
- EXPECT_EQ(".", str);
+ EXPECT_EQ(str, ".");
}
TEST(util_path_filename, alternate_slash_unix)
{
string str = path_filename("/tmp\\foo.txt");
- EXPECT_EQ("tmp\\foo.txt", str);
+ EXPECT_EQ(str, "tmp\\foo.txt");
}
#endif /* !_WIN32 */
TEST(util_path_filename, file_only)
{
string str = path_filename("foo.txt");
- EXPECT_EQ("foo.txt", str);
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_filename, empty)
{
string str = path_filename("");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
#ifdef _WIN32
TEST(util_path_filename, simple_windows)
{
string str = path_filename("C:\\tmp\\foo.txt");
- EXPECT_EQ("foo.txt", str);
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_filename, root_windows)
{
string str = path_filename("C:\\");
- EXPECT_EQ("\\", str);
+ EXPECT_EQ(str, "\\");
}
TEST(util_path_filename, last_slash_windows)
{
string str = path_filename("C:\\tmp\\foo.txt\\");
- EXPECT_EQ(".", str);
+ EXPECT_EQ(str, ".");
}
TEST(util_path_filename, alternate_slash_windows)
{
string str = path_filename("C:\\tmp/foo.txt");
- EXPECT_EQ("foo.txt", str);
+ EXPECT_EQ(str, "foo.txt");
}
#endif /* _WIN32 */
@@ -92,63 +92,63 @@ TEST(util_path_filename, alternate_slash_windows)
TEST(util_path_dirname, simple_unix)
{
string str = path_dirname("/tmp/foo.txt");
- EXPECT_EQ("/tmp", str);
+ EXPECT_EQ(str, "/tmp");
}
TEST(util_path_dirname, root_unix)
{
string str = path_dirname("/");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_path_dirname, last_slash_unix)
{
string str = path_dirname("/tmp/foo.txt/");
- EXPECT_EQ("/tmp/foo.txt", str);
+ EXPECT_EQ(str, "/tmp/foo.txt");
}
TEST(util_path_dirname, alternate_slash_unix)
{
string str = path_dirname("/tmp\\foo.txt");
- EXPECT_EQ("/", str);
+ EXPECT_EQ(str, "/");
}
#endif /* !_WIN32 */
TEST(util_path_dirname, file_only)
{
string str = path_dirname("foo.txt");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_path_dirname, empty)
{
string str = path_dirname("");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
#ifdef _WIN32
TEST(util_path_dirname, simple_windows)
{
string str = path_dirname("C:\\tmp\\foo.txt");
- EXPECT_EQ("C:\\tmp", str);
+ EXPECT_EQ(str, "C:\\tmp");
}
TEST(util_path_dirname, root_windows)
{
string str = path_dirname("C:\\");
- EXPECT_EQ("C:", str);
+ EXPECT_EQ(str, "C:");
}
TEST(util_path_dirname, last_slash_windows)
{
string str = path_dirname("C:\\tmp\\foo.txt\\");
- EXPECT_EQ("C:\\tmp\\foo.txt", str);
+ EXPECT_EQ(str, "C:\\tmp\\foo.txt");
}
TEST(util_path_dirname, alternate_slash_windows)
{
string str = path_dirname("C:\\tmp/foo.txt");
- EXPECT_EQ("C:\\tmp", str);
+ EXPECT_EQ(str, "C:\\tmp");
}
#endif /* _WIN32 */
@@ -157,152 +157,152 @@ TEST(util_path_dirname, alternate_slash_windows)
TEST(util_path_join, empty_both)
{
string str = path_join("", "");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_path_join, empty_directory)
{
string str = path_join("", "foo.txt");
- EXPECT_EQ("foo.txt", str);
+ EXPECT_EQ(str, "foo.txt");
}
TEST(util_path_join, empty_filename)
{
string str = path_join("foo", "");
- EXPECT_EQ("foo", str);
+ EXPECT_EQ(str, "foo");
}
#ifndef _WIN32
TEST(util_path_join, simple_unix)
{
string str = path_join("foo", "bar");
- EXPECT_EQ("foo/bar", str);
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, directory_slash_unix)
{
string str = path_join("foo/", "bar");
- EXPECT_EQ("foo/bar", str);
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, filename_slash_unix)
{
string str = path_join("foo", "/bar");
- EXPECT_EQ("foo/bar", str);
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, both_slash_unix)
{
string str = path_join("foo/", "/bar");
- EXPECT_EQ("foo//bar", str);
+ EXPECT_EQ(str, "foo//bar");
}
TEST(util_path_join, directory_alternate_slash_unix)
{
string str = path_join("foo\\", "bar");
- EXPECT_EQ("foo\\/bar", str);
+ EXPECT_EQ(str, "foo\\/bar");
}
TEST(util_path_join, filename_alternate_slash_unix)
{
string str = path_join("foo", "\\bar");
- EXPECT_EQ("foo/\\bar", str);
+ EXPECT_EQ(str, "foo/\\bar");
}
TEST(util_path_join, both_alternate_slash_unix)
{
string str = path_join("foo", "\\bar");
- EXPECT_EQ("foo/\\bar", str);
+ EXPECT_EQ(str, "foo/\\bar");
}
TEST(util_path_join, empty_dir_filename_slash_unix)
{
string str = path_join("", "/foo.txt");
- EXPECT_EQ("/foo.txt", str);
+ EXPECT_EQ(str, "/foo.txt");
}
TEST(util_path_join, empty_dir_filename_alternate_slash_unix)
{
string str = path_join("", "\\foo.txt");
- EXPECT_EQ("\\foo.txt", str);
+ EXPECT_EQ(str, "\\foo.txt");
}
TEST(util_path_join, empty_filename_dir_slash_unix)
{
string str = path_join("foo/", "");
- EXPECT_EQ("foo/", str);
+ EXPECT_EQ(str, "foo/");
}
TEST(util_path_join, empty_filename_dir_alternate_slash_unix)
{
string str = path_join("foo\\", "");
- EXPECT_EQ("foo\\", str);
+ EXPECT_EQ(str, "foo\\");
}
#else /* !_WIN32 */
TEST(util_path_join, simple_windows)
{
string str = path_join("foo", "bar");
- EXPECT_EQ("foo\\bar", str);
+ EXPECT_EQ(str, "foo\\bar");
}
TEST(util_path_join, directory_slash_windows)
{
string str = path_join("foo\\", "bar");
- EXPECT_EQ("foo\\bar", str);
+ EXPECT_EQ(str, "foo\\bar");
}
TEST(util_path_join, filename_slash_windows)
{
string str = path_join("foo", "\\bar");
- EXPECT_EQ("foo\\bar", str);
+ EXPECT_EQ(str, "foo\\bar");
}
TEST(util_path_join, both_slash_windows)
{
string str = path_join("foo\\", "\\bar");
- EXPECT_EQ("foo\\\\bar", str);
+ EXPECT_EQ(str, "foo\\\\bar");
}
TEST(util_path_join, directory_alternate_slash_windows)
{
string str = path_join("foo/", "bar");
- EXPECT_EQ("foo/bar", str);
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, filename_alternate_slash_windows)
{
string str = path_join("foo", "/bar");
- EXPECT_EQ("foo/bar", str);
+ EXPECT_EQ(str, "foo/bar");
}
TEST(util_path_join, both_alternate_slash_windows)
{
string str = path_join("foo/", "/bar");
- EXPECT_EQ("foo//bar", str);
+ EXPECT_EQ(str, "foo//bar");
}
TEST(util_path_join, empty_dir_filename_slash_windows)
{
string str = path_join("", "\\foo.txt");
- EXPECT_EQ("\\foo.txt", str);
+ EXPECT_EQ(str, "\\foo.txt");
}
TEST(util_path_join, empty_dir_filename_alternate_slash_windows)
{
string str = path_join("", "/foo.txt");
- EXPECT_EQ("/foo.txt", str);
+ EXPECT_EQ(str, "/foo.txt");
}
TEST(util_path_join, empty_filename_dir_slash_windows)
{
string str = path_join("foo\\", "");
- EXPECT_EQ("foo\\", str);
+ EXPECT_EQ(str, "foo\\");
}
TEST(util_path_join, empty_filename_dir_alternate_slash_windows)
{
string str = path_join("foo/", "");
- EXPECT_EQ("foo/", str);
+ EXPECT_EQ(str, "foo/");
}
#endif /* !_WIN32 */
@@ -311,31 +311,31 @@ TEST(util_path_join, empty_filename_dir_alternate_slash_windows)
TEST(util_path_escape, no_escape_chars)
{
string str = path_escape("/tmp/foo/bar");
- EXPECT_EQ("/tmp/foo/bar", str);
+ EXPECT_EQ(str, "/tmp/foo/bar");
}
TEST(util_path_escape, simple)
{
string str = path_escape("/tmp/foo bar");
- EXPECT_EQ("/tmp/foo\\ bar", str);
+ EXPECT_EQ(str, "/tmp/foo\\ bar");
}
TEST(util_path_escape, simple_end)
{
string str = path_escape("/tmp/foo/bar ");
- EXPECT_EQ("/tmp/foo/bar\\ ", str);
+ EXPECT_EQ(str, "/tmp/foo/bar\\ ");
}
TEST(util_path_escape, multiple)
{
string str = path_escape("/tmp/foo bar");
- EXPECT_EQ("/tmp/foo\\ \\ bar", str);
+ EXPECT_EQ(str, "/tmp/foo\\ \\ bar");
}
TEST(util_path_escape, simple_multiple_end)
{
string str = path_escape("/tmp/foo/bar ");
- EXPECT_EQ("/tmp/foo/bar\\ \\ ", str);
+ EXPECT_EQ(str, "/tmp/foo/bar\\ \\ ");
}
/* ******** Tests for path_is_relative() ******** */
diff --git a/intern/cycles/test/util_string_test.cpp b/intern/cycles/test/util_string_test.cpp
index e502a35704b..22ec8e0ee8e 100644
--- a/intern/cycles/test/util_string_test.cpp
+++ b/intern/cycles/test/util_string_test.cpp
@@ -25,25 +25,25 @@ CCL_NAMESPACE_BEGIN
TEST(util_string_printf, no_format)
{
string str = string_printf("foo bar");
- EXPECT_EQ(str, "foo bar");
+ EXPECT_EQ("foo bar", str);
}
TEST(util_string_printf, int_number)
{
string str = string_printf("foo %d bar", 314);
- EXPECT_EQ(str, "foo 314 bar");
+ EXPECT_EQ("foo 314 bar", str);
}
TEST(util_string_printf, float_number_default_precision)
{
string str = string_printf("foo %f bar", 3.1415);
- EXPECT_EQ(str, "foo 3.141500 bar");
+ EXPECT_EQ("foo 3.141500 bar", str);
}
TEST(util_string_printf, float_number_custom_precision)
{
string str = string_printf("foo %.1f bar", 3.1415);
- EXPECT_EQ(str, "foo 3.1 bar");
+ EXPECT_EQ("foo 3.1 bar", str);
}
/* ******** Tests for string_printf() ******** */
@@ -78,44 +78,44 @@ TEST(util_string_split, empty)
{
vector<string> tokens;
string_split(tokens, "");
- EXPECT_EQ(0, tokens.size());
+ EXPECT_EQ(tokens.size(), 0);
}
TEST(util_string_split, only_spaces)
{
vector<string> tokens;
string_split(tokens, " \t\t \t");
- EXPECT_EQ(0, tokens.size());
+ EXPECT_EQ(tokens.size(), 0);
}
TEST(util_string_split, single)
{
vector<string> tokens;
string_split(tokens, "foo");
- EXPECT_EQ(1, tokens.size());
- EXPECT_EQ("foo", tokens[0]);
+ EXPECT_EQ(tokens.size(), 1);
+ EXPECT_EQ(tokens[0], "foo");
}
TEST(util_string_split, simple)
{
vector<string> tokens;
string_split(tokens, "foo a bar b");
- EXPECT_EQ(4, tokens.size());
- EXPECT_EQ("foo", tokens[0]);
- EXPECT_EQ("a", tokens[1]);
- EXPECT_EQ("bar", tokens[2]);
- EXPECT_EQ("b", tokens[3]);
+ EXPECT_EQ(tokens.size(), 4);
+ EXPECT_EQ(tokens[0], "foo");
+ EXPECT_EQ(tokens[1], "a");
+ EXPECT_EQ(tokens[2], "bar");
+ EXPECT_EQ(tokens[3], "b");
}
TEST(util_string_split, multiple_spaces)
{
vector<string> tokens;
string_split(tokens, " \t foo \ta bar b\t ");
- EXPECT_EQ(4, tokens.size());
- EXPECT_EQ("foo", tokens[0]);
- EXPECT_EQ("a", tokens[1]);
- EXPECT_EQ("bar", tokens[2]);
- EXPECT_EQ("b", tokens[3]);
+ EXPECT_EQ(tokens.size(), 4);
+ EXPECT_EQ(tokens[0], "foo");
+ EXPECT_EQ(tokens[1], "a");
+ EXPECT_EQ(tokens[2], "bar");
+ EXPECT_EQ(tokens[3], "b");
}
/* ******** Tests for string_replace() ******** */
@@ -124,35 +124,35 @@ TEST(util_string_replace, empty_haystack_and_other)
{
string str = "";
string_replace(str, "x", "");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_replace, empty_haystack)
{
string str = "";
string_replace(str, "x", "y");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_replace, empty_other)
{
string str = "x";
string_replace(str, "x", "");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_replace, long_haystack_empty_other)
{
string str = "a x b xxc";
string_replace(str, "x", "");
- EXPECT_EQ("a b c", str);
+ EXPECT_EQ(str, "a b c");
}
TEST(util_string_replace, long_haystack)
{
string str = "a x b xxc";
string_replace(str, "x", "FOO");
- EXPECT_EQ("a FOO b FOOFOOc", str);
+ EXPECT_EQ(str, "a FOO b FOOFOOc");
}
/* ******** Tests for string_endswith() ******** */
@@ -192,25 +192,25 @@ TEST(util_string_endswith, simple_false)
TEST(util_string_strip, empty)
{
string str = string_strip("");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_strip, only_spaces)
{
string str = string_strip(" ");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_strip, no_spaces)
{
string str = string_strip("foo bar");
- EXPECT_EQ("foo bar", str);
+ EXPECT_EQ(str, "foo bar");
}
TEST(util_string_strip, with_spaces)
{
string str = string_strip(" foo bar ");
- EXPECT_EQ("foo bar", str);
+ EXPECT_EQ(str, "foo bar");
}
/* ******** Tests for string_remove_trademark() ******** */
@@ -218,31 +218,31 @@ TEST(util_string_strip, with_spaces)
TEST(util_string_remove_trademark, empty)
{
string str = string_remove_trademark("");
- EXPECT_EQ("", str);
+ EXPECT_EQ(str, "");
}
TEST(util_string_remove_trademark, no_trademark)
{
string str = string_remove_trademark("foo bar");
- EXPECT_EQ("foo bar", str);
+ EXPECT_EQ(str, "foo bar");
}
TEST(util_string_remove_trademark, only_tm)
{
string str = string_remove_trademark("foo bar(TM) zzz");
- EXPECT_EQ("foo bar zzz", str);
+ EXPECT_EQ(str, "foo bar zzz");
}
TEST(util_string_remove_trademark, only_r)
{
string str = string_remove_trademark("foo bar(R) zzz");
- EXPECT_EQ("foo bar zzz", str);
+ EXPECT_EQ(str, "foo bar zzz");
}
TEST(util_string_remove_trademark, both)
{
string str = string_remove_trademark("foo bar(TM)(R) zzz");
- EXPECT_EQ("foo bar zzz", str);
+ EXPECT_EQ(str, "foo bar zzz");
}
CCL_NAMESPACE_END
diff --git a/intern/utfconv/utfconv.h b/intern/utfconv/utfconv.h
index f00f4aeef27..d05ed61c8d8 100644
--- a/intern/utfconv/utfconv.h
+++ b/intern/utfconv/utfconv.h
@@ -93,7 +93,7 @@ wchar_t *alloc_utf16_from_8(const char *in8, size_t add);
/* Easy allocation and conversion of new utf-16 string. New string has _16 suffix. Must be deallocated with UTF16_UN_ENCODE in right order*/
#define UTF16_ENCODE(in8str) if (1) { \
- wchar_t *in8str ## _16 = alloc_utf16_from_8((char *)in8str, 0)
+ wchar_t *in8str ## _16 = alloc_utf16_from_8((const char *)in8str, 0)
#define UTF16_UN_ENCODE(in8str) \
free(in8str ## _16); } (void)0
diff --git a/make.bat b/make.bat
index 337a5517656..dd82b1ca8a7 100644
--- a/make.bat
+++ b/make.bat
@@ -5,8 +5,8 @@ REM This is for users who like to configure & build Blender with a single comman
setlocal ENABLEEXTENSIONS
set BLENDER_DIR=%~dp0
set BLENDER_DIR_NOSPACES=%BLENDER_DIR: =%
-if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" (
- echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting....
+if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" (
+ echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting....
goto EOF
)
set BUILD_DIR=%BLENDER_DIR%..\build_windows
@@ -79,7 +79,7 @@ if NOT "%1" == "" (
set NOBUILD=1
) else if "%1" == "showhash" (
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Branch_hash=%%i
- cd release/datafiles/locale
+ cd release/datafiles/locale
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Locale_hash=%%i
cd %~dp0
cd release/scripts/addons
@@ -132,13 +132,13 @@ if "%BUILD_ARCH%"=="x64" (
if "%target%"=="Release" (
- rem for vc12 check for both cuda 7.5 and 8
+ rem for vc12 check for both cuda 7.5 and 8
if "%CUDA_PATH%"=="" (
echo Cuda Not found, aborting!
goto EOF
)
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
- -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
+ -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
)
:DetectMSVC
@@ -157,7 +157,7 @@ if DEFINED MSVC_VC_DIR goto msvc_detect_finally
if DEFINED MSVC_VC_DIR call "%MSVC_VC_DIR%\vcvarsall.bat"
if DEFINED MSVC_VC_DIR goto sanity_checks
-rem MSVC Build environment 2017 and up.
+rem MSVC Build environment 2017 and up.
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SXS\VS7" /v %BUILD_VS_VER%.0 2^>nul`) DO set MSVC_VS_DIR=%%C
if DEFINED MSVC_VS_DIR goto msvc_detect_finally_2017
REM Check 32 bits
@@ -202,7 +202,7 @@ if NOT EXIST %BLENDER_DIR%..\lib\nul (
if "%TARGET%"=="" (
echo Error: Convenience target not set
echo This is required for building, aborting!
- echo .
+ echo .
goto HELP
)
@@ -266,15 +266,15 @@ echo.
echo At any point you can optionally modify your build configuration by editing:
echo "%BUILD_DIR%\CMakeCache.txt", then run "make" again to build with the changes applied.
echo.
-echo Blender successfully built, run from: "%BUILD_DIR%\bin\%BUILD_TYPE%"
+echo Blender successfully built, run from: "%BUILD_DIR%\bin\%BUILD_TYPE%\blender.exe"
echo.
goto EOF
:HELP
echo.
echo Convenience targets
- echo - release ^(identical to the offical blender.org builds^)
+ echo - release ^(identical to the official blender.org builds^)
echo - full ^(same as release minus the cuda kernels^)
- echo - lite
+ echo - lite
echo - headless
echo - cycles
echo - bpy
@@ -289,11 +289,10 @@ goto EOF
echo - with_tests ^(enable building unit tests^)
echo - debug ^(Build an unoptimized debuggable build^)
echo - packagename [newname] ^(override default cpack package name^)
- echo - x86 ^(override host autodetect and build 32 bit code^)
- echo - x64 ^(override host autodetect and build 64 bit code^)
+ echo - x86 ^(override host auto-detect and build 32 bit code^)
+ echo - x64 ^(override host auto-detect and build 64 bit code^)
echo - 2013 ^(build with visual studio 2013^)
echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL]
echo.
:EOF
-
diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg
index e9c114ba1bd..d88788fa904 100644
--- a/release/datafiles/blender_icons.svg
+++ b/release/datafiles/blender_icons.svg
@@ -14,7 +14,7 @@
height="640"
id="svg2"
sodipodi:version="0.32"
- inkscape:version="0.91 r"
+ inkscape:version="0.91 r13725"
version="1.0"
sodipodi:docname="blender_icons.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
@@ -31338,6 +31338,26 @@
d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" />
</clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-6"
+ id="linearGradient18199"
+ gradientUnits="userSpaceOnUse"
+ x1="189.76083"
+ y1="248.13905"
+ x2="116.05637"
+ y2="183.6826" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="radialGradient23167-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.99220964,-0.12457927,0.11585516,0.92272644,-34.13325,22.766225)"
+ cx="-0.78262758"
+ cy="294.63174"
+ fx="-0.78262758"
+ fy="294.63174"
+ r="6.6750002" />
</defs>
<sodipodi:namedview
id="base"
@@ -31349,16 +31369,16 @@
objecttolerance="10000"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="14.413868"
- inkscape:cx="480.24726"
- inkscape:cy="269.95478"
+ inkscape:zoom="19.997864"
+ inkscape:cx="462.52244"
+ inkscape:cy="435.14241"
inkscape:document-units="px"
- inkscape:current-layer="layer1"
+ inkscape:current-layer="g23149-4"
showgrid="true"
- inkscape:window-width="1680"
- inkscape:window-height="1020"
- inkscape:window-x="0"
- inkscape:window-y="30"
+ inkscape:window-width="1920"
+ inkscape:window-height="1025"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
showguides="true"
@@ -92660,6 +92680,56 @@
style="opacity:0.51999996;fill:url(#radialGradient21448-8-143);fill-opacity:1;fill-rule:evenodd;stroke:none" />
</g>
</g>
+ <g
+ transform="translate(335.99871,21.048284)"
+ style="display:inline;enable-background:new"
+ id="ICON_ROTATE-7">
+ <rect
+ y="178"
+ x="110"
+ height="16"
+ width="16"
+ id="rect37989-8"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;enable-background:accumulate" />
+ <path
+ style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:2.4000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:new"
+ d="m 114.5,192.5 -3,0 0,-3 m 13,0 0,3 -3,0 m -0.25,-13 3.25,0 0,3 m -13,0 0,-3 3,0"
+ id="path37498-7"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="rect38140-7"
+ d="m 114.5,192.5 -3,0 0,-3 m 13,0 0,3 -3,0 m -0.25,-13 3.25,0 0,3 m -13,0 0,-3 3,0"
+ style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient18199);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.59971056,0,0,0.59971056,116.78278,9.7425599)"
+ style="display:inline;enable-background:new"
+ id="g23145-9">
+ <g
+ id="g23149-4">
+ <path
+ id="path39832-9"
+ style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#1a1a1a;stroke-width:4.66725159;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ d="m -4.3682386,287.81345 1.5,0 c 0.999089,0 2.07885534,1.30514 2.50490386,2.78207 1.06592652,3.69512 2.80867074,9.82446 5.88525404,9.96406 2.6782554,0 1.6181317,-5.11535 3.1736046,-5.26275 l 0.25,0"
+ sodipodi:nodetypes="cssccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccscc"
+ d="m 9.3647983,295.22328 -0.4793018,0 c -2.2335161,0 0.1796731,4.94901 -3.4398065,5.09984 -4.44796752,0.18536 -5.37272213,-12.59185 -8.0767581,-12.56237 l -2,0"
+ style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#a8df84;stroke-width:2.93474906;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="path39834-2"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path39836-9"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.35;fill:none;stroke:url(#radialGradient23167-6);stroke-width:3.53503864;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ d="M 5.6770841,300.48165 C 0.7393262,300.21066 0.54777814,287.99792 -2.9522219,287.99792"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
</g>
<g
inkscape:groupmode="layer"
diff --git a/release/datafiles/blender_icons16/icon16_normalize_fcurves.dat b/release/datafiles/blender_icons16/icon16_normalize_fcurves.dat
new file mode 100644
index 00000000000..fe118a23d79
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_normalize_fcurves.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_normalize_fcurves.dat b/release/datafiles/blender_icons32/icon32_normalize_fcurves.dat
new file mode 100644
index 00000000000..5b1f546a563
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_normalize_fcurves.dat
Binary files differ
diff --git a/release/scripts/freestyle/modules/parameter_editor.py b/release/scripts/freestyle/modules/parameter_editor.py
index 93305cb7c5a..b093920a4cb 100644
--- a/release/scripts/freestyle/modules/parameter_editor.py
+++ b/release/scripts/freestyle/modules/parameter_editor.py
@@ -1170,6 +1170,7 @@ class Seed:
_seed = Seed()
+
def get_dashed_pattern(linestyle):
"""Extracts the dashed pattern from the various UI options """
pattern = []
@@ -1185,6 +1186,15 @@ def get_dashed_pattern(linestyle):
return pattern
+def get_grouped_objects(group):
+ for ob in group.objects:
+ if ob.dupli_type == 'GROUP' and ob.dupli_group is not None:
+ for dupli in get_grouped_objects(ob.dupli_group):
+ yield dupli
+ else:
+ yield ob
+
+
integration_types = {
'MEAN': IntegrationType.MEAN,
'MIN': IntegrationType.MIN,
@@ -1267,7 +1277,7 @@ def process(layer_name, lineset_name):
# prepare selection criteria by group of objects
if lineset.select_by_group:
if lineset.group is not None:
- names = {getQualifiedObjectName(ob): True for ob in lineset.group.objects}
+ names = {getQualifiedObjectName(ob): True for ob in get_grouped_objects(lineset.group)}
upred = ObjectNamesUP1D(names, lineset.group_negation == 'EXCLUSIVE')
selection_criteria.append(upred)
# prepare selection criteria by image border
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index d66fb08bcd6..b24b574f37b 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -1320,7 +1320,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row.prop(md, "thickness_vertex_group", text="Factor")
col.prop(md, "use_crease", text="Crease Edges")
- col.prop(md, "crease_weight", text="Crease Weight")
+ row = col.row()
+ row.active = md.use_crease
+ row.prop(md, "crease_weight", text="Crease Weight")
col = split.column()
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 3ff7a248c60..4a596981983 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -152,6 +152,33 @@ class OBJECT_PT_relations(ObjectButtonsPanel, Panel):
sub.active = (parent is not None)
+class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
+ bl_label = "Relations Extras"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+
+ split = layout.split()
+
+ if context.scene.render.engine != 'BLENDER_GAME':
+ col = split.column()
+ col.label(text="Tracking Axes:")
+ col.prop(ob, "track_axis", text="Axis")
+ col.prop(ob, "up_axis", text="Up Axis")
+
+ col = split.column()
+ col.prop(ob, "use_slow_parent")
+ row = col.row()
+ row.active = ((ob.parent is not None) and (ob.use_slow_parent))
+ row.prop(ob, "slow_parent_offset", text="Offset")
+
+ layout.prop(ob, "use_extra_recalc_object")
+ layout.prop(ob, "use_extra_recalc_data")
+
+
class GROUP_MT_specials(Menu):
bl_label = "Group Specials"
@@ -296,33 +323,6 @@ class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
layout.prop(ob, "dupli_group", text="Group")
-class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
- bl_label = "Relations Extras"
- bl_options = {'DEFAULT_CLOSED'}
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.object
-
- split = layout.split()
-
- if context.scene.render.engine != 'BLENDER_GAME':
- col = split.column()
- col.label(text="Tracking Axes:")
- col.prop(ob, "track_axis", text="Axis")
- col.prop(ob, "up_axis", text="Up Axis")
-
- col = split.column()
- col.prop(ob, "use_slow_parent")
- row = col.row()
- row.active = ((ob.parent is not None) and (ob.use_slow_parent))
- row.prop(ob, "slow_parent_offset", text="Offset")
-
- layout.prop(ob, "use_extra_recalc_object")
- layout.prop(ob, "use_extra_recalc_data")
-
-
from bl_ui.properties_animviz import (
MotionPathButtonsPanel,
OnionSkinButtonsPanel,
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 446df9e6e79..cec3b26f35a 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -42,10 +42,11 @@ class GRAPH_HT_header(Header):
dopesheet_filter(layout, context)
- layout.prop(st, "use_normalization", text="Normalize")
- row = layout.row()
- row.active = st.use_normalization
- row.prop(st, "use_auto_normalization", text="Auto")
+ row = layout.row(align=True)
+ row.prop(st, "use_normalization", icon='NORMALIZE_FCURVES', text="Normalize", toggle=True)
+ sub = row.row(align=True)
+ sub.active = st.use_normalization
+ sub.prop(st, "use_auto_normalization", icon='FILE_REFRESH', text="", toggle=True)
row = layout.row(align=True)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 6bb516cf929..8ab5b4724b8 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -652,17 +652,39 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
col.prop(strip, "rotation_start", text="Rotation")
elif strip.type == 'MULTICAM':
- layout.prop(strip, "multicam_source")
-
- row = layout.row(align=True)
- sub = row.row(align=True)
- sub.scale_x = 2.0
-
- sub.operator("screen.animation_play", text="", icon='PAUSE' if context.screen.is_animation_playing else 'PLAY')
+ col = layout.column(align=True)
+ strip_channel = strip.channel
+
+ col.prop(strip, "multicam_source", text="Source Channel")
+
+ # The multicam strip needs at least 2 strips to be useful
+ if strip_channel > 2:
+ BT_ROW = 4
+
+ col.label("Cut To:")
+ row = col.row()
+
+ for i in range(1, strip_channel):
+ if (i % BT_ROW) == 1:
+ row = col.row(align=True)
+
+ # Workaround - .active has to have a separate UI block to work
+ if i == strip.multicam_source:
+ sub = row.row(align=True)
+ sub.active = False
+ sub.operator("sequencer.cut_multicam", text="%d" % i).camera = i
+ else:
+ sub_1 = row.row(align=True)
+ sub_1.active = True
+ sub_1.operator("sequencer.cut_multicam", text="%d" % i).camera = i
+
+ if strip.channel > BT_ROW and (strip_channel - 1) % BT_ROW:
+ for i in range(strip.channel, strip_channel + ((BT_ROW + 1 - strip_channel) % BT_ROW)):
+ row.label("")
+ else:
+ col.separator()
+ col.label(text="Two or more channels are needed below this strip.", icon="INFO")
- row.label("Cut To")
- for i in range(1, strip.channel):
- row.operator("sequencer.cut_multicam", text="%d" % i).camera = i
elif strip.type == 'TEXT':
col = layout.column()
diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index 508e62e4f56..1f62d8d6968 100644
--- a/release/scripts/startup/bl_ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -49,7 +49,10 @@ class TIME_HT_header(Header):
row.prop(scene, "frame_preview_start", text="Start")
row.prop(scene, "frame_preview_end", text="End")
- layout.prop(scene, "frame_current", text="")
+ if scene.show_subframe:
+ layout.prop(scene, "frame_float", text="")
+ else:
+ layout.prop(scene, "frame_current", text="")
layout.separator()
@@ -135,6 +138,7 @@ class TIME_MT_view(Menu):
layout.prop(st, "show_frame_indicator")
layout.prop(scene, "show_keys_from_selected_only")
+ layout.prop(scene, "show_subframe")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 5e936076d0e..b6479df3047 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1346,9 +1346,9 @@ class VIEW3D_MT_object_clear(Menu):
def draw(self, context):
layout = self.layout
- layout.operator("object.location_clear", text="Location")
- layout.operator("object.rotation_clear", text="Rotation")
- layout.operator("object.scale_clear", text="Scale")
+ layout.operator("object.location_clear", text="Location").clear_delta = False
+ layout.operator("object.rotation_clear", text="Rotation").clear_delta = False
+ layout.operator("object.scale_clear", text="Scale").clear_delta = False
layout.operator("object.origin_clear", text="Origin")
@@ -1744,6 +1744,7 @@ class VIEW3D_MT_brush_paint_modes(Menu):
layout.prop(brush, "use_paint_weight", text="Weight Paint")
layout.prop(brush, "use_paint_image", text="Texture Paint")
+
# ********** Vertex paint menu **********
@@ -1813,6 +1814,7 @@ class VIEW3D_MT_vertex_group(Menu):
layout.operator("object.vertex_group_remove", text="Remove Active Group").all = False
layout.operator("object.vertex_group_remove", text="Remove All Groups").all = True
+
# ********** Weight paint menu **********
@@ -1851,6 +1853,7 @@ class VIEW3D_MT_paint_weight(Menu):
layout.operator("paint.weight_set")
+
# ********** Sculpt menu **********
@@ -2004,6 +2007,7 @@ class VIEW3D_MT_particle_specials(Menu):
class VIEW3D_MT_particle_showhide(ShowHideMenu, Menu):
_operator_name = "particle"
+
# ********** Pose Menu **********
@@ -2277,6 +2281,7 @@ class VIEW3D_MT_bone_options_disable(Menu, BoneOptions):
bl_label = "Disable Bone Options"
type = 'DISABLE'
+
# ********** Edit Menus, suffix from ob.type **********
@@ -2444,6 +2449,7 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
with_bullet = bpy.app.build_options.bullet
layout.operator("mesh.merge")
+ layout.operator("mesh.remove_doubles")
layout.operator("mesh.rip_move")
layout.operator("mesh.rip_move_fill")
layout.operator("mesh.rip_edge_move")
@@ -2466,7 +2472,6 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
if with_bullet:
layout.operator("mesh.convex_hull")
layout.operator("mesh.vertices_smooth")
- layout.operator("mesh.remove_doubles")
layout.operator("mesh.blend_from_shape")
@@ -2623,6 +2628,7 @@ class VIEW3D_MT_edit_mesh_clean(Menu):
layout.operator("mesh.face_make_planar")
layout.operator("mesh.vert_connect_nonplanar")
layout.operator("mesh.vert_connect_concave")
+ layout.operator("mesh.remove_doubles")
layout.operator("mesh.fill_holes")
diff --git a/source/blender/alembic/intern/abc_archive.cc b/source/blender/alembic/intern/abc_archive.cc
index 0985a06d732..5f8fc1a3739 100644
--- a/source/blender/alembic/intern/abc_archive.cc
+++ b/source/blender/alembic/intern/abc_archive.cc
@@ -113,25 +113,25 @@ static OArchive create_archive(std::ostream *ostream,
Alembic::Abc::MetaData &md,
bool ogawa)
{
- md.set(Alembic::Abc::kApplicationNameKey, "Blender");
+ md.set(Alembic::Abc::kApplicationNameKey, "Blender");
md.set(Alembic::Abc::kUserDescriptionKey, scene_name);
- time_t raw_time;
- time(&raw_time);
- char buffer[128];
+ time_t raw_time;
+ time(&raw_time);
+ char buffer[128];
#if defined _WIN32 || defined _WIN64
- ctime_s(buffer, 128, &raw_time);
+ ctime_s(buffer, 128, &raw_time);
#else
- ctime_r(&raw_time, buffer);
+ ctime_r(&raw_time, buffer);
#endif
- const std::size_t buffer_len = strlen(buffer);
- if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') {
- buffer[buffer_len - 1] = '\0';
- }
+ const std::size_t buffer_len = strlen(buffer);
+ if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') {
+ buffer[buffer_len - 1] = '\0';
+ }
- md.set(Alembic::Abc::kDateWrittenKey, buffer);
+ md.set(Alembic::Abc::kDateWrittenKey, buffer);
ErrorHandler::Policy policy = ErrorHandler::kThrowPolicy;
diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc
index 4ecb9d944f2..0542255d84b 100644
--- a/source/blender/alembic/intern/abc_curves.cc
+++ b/source/blender/alembic/intern/abc_curves.cc
@@ -102,7 +102,7 @@ void AbcCurveWriter::do_write()
const BPoint *point = nurbs->bp;
for (int i = 0; i < totpoint; ++i, ++point) {
- copy_zup_yup(temp_vert.getValue(), point->vec);
+ copy_yup_from_zup(temp_vert.getValue(), point->vec);
verts.push_back(temp_vert);
weights.push_back(point->vec[3]);
widths.push_back(point->radius);
@@ -118,7 +118,7 @@ void AbcCurveWriter::do_write()
/* TODO(kevin): store info about handles, Alembic doesn't have this. */
for (int i = 0; i < totpoint; ++i, ++bezier) {
- copy_zup_yup(temp_vert.getValue(), bezier->vec[1]);
+ copy_yup_from_zup(temp_vert.getValue(), bezier->vec[1]);
verts.push_back(temp_vert);
widths.push_back(bezier->radius);
}
@@ -322,7 +322,7 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
weight = (*weights)[idx];
}
- copy_yup_zup(bp->vec, pos.getValue());
+ copy_zup_from_yup(bp->vec, pos.getValue());
bp->vec[3] = weight;
bp->f1 = SELECT;
bp->radius = radius;
@@ -361,7 +361,7 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
* object directly and create a new DerivedMesh from that. Also we might need to
* create new or delete existing NURBS in the curve.
*/
-DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float time, int /*read_flag*/, const char **/*err_str*/)
+DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/, const float time, int /*read_flag*/, const char ** /*err_str*/)
{
ISampleSelector sample_sel(time);
const ICurvesSchema::Sample sample = m_curves_schema.getValue(sample_sel);
@@ -389,7 +389,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float t
for (int i = 0; i < totpoint; ++i, ++point, ++vertex_idx) {
const Imath::V3f &pos = (*positions)[vertex_idx];
- copy_yup_zup(point->vec, pos.getValue());
+ copy_zup_from_yup(point->vec, pos.getValue());
}
}
else if (nurbs->bezt) {
@@ -397,7 +397,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float t
for (int i = 0; i < totpoint; ++i, ++bezier, ++vertex_idx) {
const Imath::V3f &pos = (*positions)[vertex_idx];
- copy_yup_zup(bezier->vec[1], pos.getValue());
+ copy_zup_from_yup(bezier->vec[1], pos.getValue());
}
}
}
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index ff8b0442ab6..90a99469389 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -47,7 +47,7 @@ extern "C" {
#ifdef WIN32
/* needed for MSCV because of snprintf from BLI_string */
-# include "BLI_winstuff.h"
+# include "BLI_winstuff.h"
#endif
#include "BKE_anim.h"
@@ -382,7 +382,10 @@ void AbcExporter::createTransformWritersFlat()
void AbcExporter::exploreTransform(EvaluationContext *eval_ctx, Object *ob, Object *parent, Object *dupliObParent)
{
- createTransformWriter(ob, parent, dupliObParent);
+
+ if (export_object(&m_settings, ob) && object_is_shape(ob)) {
+ createTransformWriter(ob, parent, dupliObParent);
+ }
ListBase *lb = object_duplilist(eval_ctx, m_scene, ob);
@@ -410,8 +413,12 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl
{
const std::string name = get_object_dag_path_name(ob, dupliObParent);
+ /* An object should not be its own parent, or we'll get infinite loops. */
+ BLI_assert(ob != parent);
+ BLI_assert(ob != dupliObParent);
+
/* check if we have already created a transform writer for this object */
- if (m_xforms.find(name) != m_xforms.end()){
+ if (getXForm(name) != NULL){
std::cerr << "xform " << name << " already exists\n";
return;
}
@@ -426,6 +433,14 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl
if (parent->parent) {
createTransformWriter(parent, parent->parent, dupliObParent);
}
+ else if (parent == dupliObParent) {
+ if (dupliObParent->parent == NULL) {
+ createTransformWriter(parent, NULL, NULL);
+ }
+ else {
+ createTransformWriter(parent, dupliObParent->parent, dupliObParent->parent);
+ }
+ }
else {
createTransformWriter(parent, dupliObParent, dupliObParent);
}
diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc
index 14bcf6731ea..e328df24e53 100644
--- a/source/blender/alembic/intern/abc_hair.cc
+++ b/source/blender/alembic/intern/abc_hair.cc
@@ -77,7 +77,6 @@ void AbcHairWriter::do_write()
DerivedMesh *dm = mesh_create_derived_view(m_scene, m_object, CD_MASK_MESH);
DM_ensure_tessface(dm);
- DM_update_tessface_data(dm);
std::vector<Imath::V3f> verts;
std::vector<int32_t> hvertices;
@@ -164,7 +163,7 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
psys_interpolate_face(mverts, face, tface, NULL, mapfw, vec, normal, NULL, NULL, NULL, NULL);
- copy_zup_yup(tmp_nor.getValue(), normal);
+ copy_yup_from_zup(tmp_nor.getValue(), normal);
norm_values.push_back(tmp_nor);
}
}
@@ -198,7 +197,7 @@ void AbcHairWriter::write_hair_sample(DerivedMesh *dm,
MVert *mv = mverts + vtx[o];
normal_short_to_float_v3(normal, mv->no);
- copy_zup_yup(tmp_nor.getValue(), normal);
+ copy_yup_from_zup(tmp_nor.getValue(), normal);
norm_values.push_back(tmp_nor);
found = true;
break;
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index bdd75f93189..8bc9c335054 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -112,7 +112,7 @@ static void get_vertices(DerivedMesh *dm, std::vector<Imath::V3f> &points)
MVert *verts = dm->getVertArray(dm);
for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) {
- copy_zup_yup(points[i].getValue(), verts[i].co);
+ copy_yup_from_zup(points[i].getValue(), verts[i].co);
}
}
@@ -182,7 +182,7 @@ static void get_vertex_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals
for (int i = 0, e = dm->getNumVerts(dm); i < e; ++i) {
normal_short_to_float_v3(no, verts[i].no);
- copy_zup_yup(normals[i].getValue(), no);
+ copy_yup_from_zup(normals[i].getValue(), no);
}
}
@@ -211,7 +211,7 @@ static void get_loop_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals)
for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
const int index = ml->v;
- copy_zup_yup(normals[loop_index].getValue(), lnors[index]);
+ copy_yup_from_zup(normals[loop_index].getValue(), lnors[index]);
}
}
}
@@ -226,14 +226,14 @@ static void get_loop_normals(DerivedMesh *dm, std::vector<Imath::V3f> &normals)
BKE_mesh_calc_poly_normal(mp, ml - (mp->totloop - 1), verts, no);
for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
- copy_zup_yup(normals[loop_index].getValue(), no);
+ copy_yup_from_zup(normals[loop_index].getValue(), no);
}
}
else {
/* Smooth shaded, use individual vert normals. */
for (int j = 0; j < mp->totloop; --ml, ++j, ++loop_index) {
normal_short_to_float_v3(no, verts[ml->v].no);
- copy_zup_yup(normals[loop_index].getValue(), no);
+ copy_yup_from_zup(normals[loop_index].getValue(), no);
}
}
}
@@ -590,7 +590,7 @@ void AbcMeshWriter::getVelocities(DerivedMesh *dm, std::vector<Imath::V3f> &vels
float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities);
for (int i = 0; i < totverts; ++i) {
- copy_zup_yup(vels[i].getValue(), mesh_vels);
+ copy_yup_from_zup(vels[i].getValue(), mesh_vels);
mesh_vels += 3;
}
}
@@ -726,7 +726,7 @@ static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions
const Imath::V3f &ceil_pos = (*ceil_positions)[i];
interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), weight);
- copy_yup_zup(mvert.co, tmp);
+ copy_zup_from_yup(mvert.co, tmp);
mvert.bweight = 0;
}
@@ -755,7 +755,7 @@ void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArr
MVert &mvert = mverts[i];
Imath::V3f pos_in = (*positions)[i];
- copy_yup_zup(mvert.co, pos_in.getValue());
+ copy_zup_from_yup(mvert.co, pos_in.getValue());
mvert.bweight = 0;
@@ -765,7 +765,7 @@ void read_mverts(MVert *mverts, const P3fArraySamplePtr &positions, const N3fArr
short no[3];
normal_float_to_short_v3(no, nor_in.getValue());
- copy_yup_zup(mvert.no, no);
+ copy_zup_from_yup(mvert.no, no);
}
}
}
diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_nurbs.cc
index 4f57dfdae9e..d0b9561f679 100644
--- a/source/blender/alembic/intern/abc_nurbs.cc
+++ b/source/blender/alembic/intern/abc_nurbs.cc
@@ -153,7 +153,7 @@ void AbcNurbsWriter::do_write()
const BPoint *bp = nu->bp;
for (int i = 0; i < size; ++i, ++bp) {
- copy_zup_yup(positions[i].getValue(), bp->vec);
+ copy_yup_from_zup(positions[i].getValue(), bp->vec);
weights[i] = bp->vec[3];
}
@@ -281,7 +281,7 @@ void AbcNurbsReader::readObjectData(Main *bmain, float time)
posw_in = (*weights)[i];
}
- copy_yup_zup(bp->vec, pos_in.getValue());
+ copy_zup_from_yup(bp->vec, pos_in.getValue());
bp->vec[3] = posw_in;
bp->f1 = SELECT;
bp->radius = 1.0f;
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index 9dfccdb8c7f..a5b8af542fc 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -97,14 +97,14 @@ Imath::Box3d AbcObjectWriter::bounds()
return Imath::Box3d();
}
- /* Convert Z-up to Y-up. */
+ /* Convert Z-up to Y-up. This also changes which vector goes into which min/max property. */
this->m_bounds.min.x = bb->vec[0][0];
this->m_bounds.min.y = bb->vec[0][2];
- this->m_bounds.min.z = -bb->vec[0][1];
+ this->m_bounds.min.z = -bb->vec[6][1];
this->m_bounds.max.x = bb->vec[6][0];
this->m_bounds.max.y = bb->vec[6][2];
- this->m_bounds.max.z = -bb->vec[6][1];
+ this->m_bounds.max.z = -bb->vec[0][1];
return this->m_bounds;
}
diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc
index 4c78f3e83c7..fc84759b1d9 100644
--- a/source/blender/alembic/intern/abc_points.cc
+++ b/source/blender/alembic/intern/abc_points.cc
@@ -200,7 +200,7 @@ void read_points_sample(const IPointsSchema &schema,
read_mverts(config.mvert, positions, vnormals);
}
-DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/, const char **/*err_str*/)
+DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/, const char ** /*err_str*/)
{
ISampleSelector sample_sel(time);
const IPointsSchema::Sample sample = m_schema.getValue(sample_sel);
diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc
index e2fc7674c4e..2c6ef09326c 100644
--- a/source/blender/alembic/intern/abc_transform.cc
+++ b/source/blender/alembic/intern/abc_transform.cc
@@ -122,7 +122,7 @@ Imath::Box3d AbcTransformWriter::bounds()
return Imath::transform(bounds, m_matrix);
}
-bool AbcTransformWriter::hasAnimation(Object */*ob*/) const
+bool AbcTransformWriter::hasAnimation(Object * /*ob*/) const
{
/* TODO(kevin): implement this. */
return true;
@@ -146,6 +146,6 @@ bool AbcEmptyReader::valid() const
void AbcEmptyReader::readObjectData(Main *bmain, float /*time*/)
{
- m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str());
+ m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_data_name.c_str());
m_object->data = NULL;
}
diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc
index f8ce72d845d..08c94f437e6 100644
--- a/source/blender/alembic/intern/abc_util.cc
+++ b/source/blender/alembic/intern/abc_util.cc
@@ -197,7 +197,7 @@ void create_transform_matrix(float r_mat[4][4])
copy_m4_m3(transform_mat, rot_mat);
/* Add translation to transformation matrix. */
- copy_yup_zup(transform_mat[3], loc);
+ copy_zup_from_yup(transform_mat[3], loc);
/* Create scale matrix. */
scale_mat[0][0] = scale[0];
@@ -417,7 +417,7 @@ void create_transform_matrix(Object *obj, float transform_mat[4][4])
copy_m4_m3(transform_mat, rot_mat);
/* Add translation to transformation matrix. */
- copy_zup_yup(transform_mat[3], loc);
+ copy_yup_from_zup(transform_mat[3], loc);
/* Create scale matrix. */
scale_mat[0][0] = scale[0];
diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h
index 60a96855d14..a7ac9df91c7 100644
--- a/source/blender/alembic/intern/abc_util.h
+++ b/source/blender/alembic/intern/abc_util.h
@@ -116,14 +116,14 @@ AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSe
/* Copy from Y-up to Z-up. */
-ABC_INLINE void copy_yup_zup(float zup[3], const float yup[3])
+ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
{
zup[0] = yup[0];
zup[1] = -yup[2];
zup[2] = yup[1];
}
-ABC_INLINE void copy_yup_zup(short zup[3], const short yup[3])
+ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3])
{
zup[0] = yup[0];
zup[1] = -yup[2];
@@ -132,14 +132,14 @@ ABC_INLINE void copy_yup_zup(short zup[3], const short yup[3])
/* Copy from Z-up to Y-up. */
-ABC_INLINE void copy_zup_yup(float yup[3], const float zup[3])
+ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
{
yup[0] = zup[0];
yup[1] = zup[2];
yup[2] = -zup[1];
}
-ABC_INLINE void copy_zup_yup(short yup[3], const short zup[3])
+ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3])
{
yup[0] = zup[0];
yup[1] = zup[2];
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 07db2217bac..ad729ad37dd 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -104,7 +104,7 @@ typedef struct BVHTreeFromMesh {
* The tree is build in mesh space coordinates, this means special care must be made on queries
* so that the coordinates and rays are first translated on the mesh local coordinates.
* Reason for this is that bvh_from_mesh_* can use a cache in some cases and so it becomes possible to reuse a BVHTree.
- *
+ *
* free_bvhtree_from_mesh should be called when the tree is no longer needed.
*/
BVHTree *bvhtree_from_editmesh_verts(
@@ -118,7 +118,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(
BVHTree *bvhtree_from_mesh_verts(
struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
BVHTree *bvhtree_from_mesh_verts_ex(
- struct BVHTreeFromMesh *data, struct MVert *vert, const int numVerts,
+ struct BVHTreeFromMesh *data, const struct MVert *vert, const int numVerts,
const bool vert_allocated, const BLI_bitmap *mask, int verts_num_active,
float epsilon, int tree_type, int axis);
@@ -133,14 +133,20 @@ BVHTree *bvhtree_from_editmesh_edges_ex(
BVHTree *bvhtree_from_mesh_edges(
struct BVHTreeFromMesh *data, struct DerivedMesh *mesh,
float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_mesh_edges_ex(
+ struct BVHTreeFromMesh *data,
+ const struct MVert *vert, const bool vert_allocated,
+ const struct MEdge *edge, const int edges_num, const bool edge_allocated,
+ const BLI_bitmap *edges_mask, int edges_num_active,
+ float epsilon, int tree_type, int axis);
BVHTree *bvhtree_from_mesh_faces(
struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon,
int tree_type, int axis);
BVHTree *bvhtree_from_mesh_faces_ex(
struct BVHTreeFromMesh *data,
- struct MVert *vert, const bool vert_allocated,
- struct MFace *face, const int numFaces, const bool face_allocated,
+ const struct MVert *vert, const bool vert_allocated,
+ const struct MFace *face, const int numFaces, const bool face_allocated,
const BLI_bitmap *mask, int numFaces_active,
float epsilon, int tree_type, int axis);
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index 9948f21ba90..4876461bfe0 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -79,6 +79,7 @@ DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispba
*/
struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm);
struct DerivedMesh *CDDM_copy_from_tessface(struct DerivedMesh *dm);
+struct DerivedMesh *CDDM_copy_with_tessface(struct DerivedMesh *dm);
/* creates a CDDerivedMesh with the same layer stack configuration as the
* given DerivedMesh and containing the requested numbers of elements.
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index d812ab832a1..89adbc4338f 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -139,8 +139,6 @@ void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], cons
void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]);
void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]);
void BKE_boundbox_minmax(const struct BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3]);
-struct BoundBox *BKE_boundbox_ensure_minimum_dimensions(
- struct BoundBox *bb, struct BoundBox *bb_temp, const float epsilon);
struct BoundBox *BKE_object_boundbox_get(struct Object *ob);
void BKE_object_dimensions_get(struct Object *ob, float vec[3]);
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 1c5ea946f59..9a60eb29957 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -42,6 +42,7 @@ struct Brush;
struct ColorBand;
struct EnvMap;
struct FreestyleLineStyle;
+struct ImagePool;
struct Lamp;
struct Main;
struct Material;
@@ -133,6 +134,12 @@ struct OceanTex *BKE_texture_ocean_copy(struct OceanTex *ot);
bool BKE_texture_dependsOnTime(const struct Tex *texture);
bool BKE_texture_is_image_user(const struct Tex *tex);
+void BKE_texture_get_value_ex(
+ const struct Scene *scene, struct Tex *texture,
+ float *tex_co, struct TexResult *texres,
+ struct ImagePool *pool,
+ bool use_color_management);
+
void BKE_texture_get_value(
const struct Scene *scene, struct Tex *texture,
float *tex_co, struct TexResult *texres, bool use_color_management);
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index b1dcc40279f..9236a1b5853 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -121,7 +121,7 @@ static bool test_path(char *targetpath, const char *path_base, const char *path_
if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
- /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
+ /* rare cases folder_name is omitted (when looking for ~/.config/blender/2.xx dir only) */
if (folder_name)
BLI_make_file_string("/", targetpath, tmppath, folder_name);
else
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 0287d6ae9ca..02cc31e5977 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1037,6 +1037,17 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
if (use_dverts) {
defnrToPC = MEM_callocN(sizeof(*defnrToPC) * defbase_tot, "defnrToBone");
defnrToPCIndex = MEM_callocN(sizeof(*defnrToPCIndex) * defbase_tot, "defnrToIndex");
+ /* TODO(sergey): Some considerations here:
+ *
+ * - Make it more generic function, maybe even keep together with chanhash.
+ * - Check whether keeping this consistent across frames gives speedup.
+ * - Don't use hash for small armatures.
+ */
+ GHash *idx_hash = BLI_ghash_ptr_new("pose channel index by name");
+ int pchan_index = 0;
+ for (pchan = armOb->pose->chanbase.first; pchan != NULL; pchan = pchan->next, ++pchan_index) {
+ BLI_ghash_insert(idx_hash, pchan, SET_INT_IN_POINTER(pchan_index));
+ }
for (i = 0, dg = target->defbase.first; dg; i++, dg = dg->next) {
defnrToPC[i] = BKE_pose_channel_find_name(armOb->pose, dg->name);
/* exclude non-deforming bones */
@@ -1045,10 +1056,11 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float
defnrToPC[i] = NULL;
}
else {
- defnrToPCIndex[i] = BLI_findindex(&armOb->pose->chanbase, defnrToPC[i]);
+ defnrToPCIndex[i] = GET_INT_FROM_POINTER(BLI_ghash_lookup(idx_hash, defnrToPC[i]));
}
}
}
+ BLI_ghash_free(idx_hash, NULL, NULL);
}
}
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index a8670395fc4..afd60102453 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -234,7 +234,7 @@ int BKE_blender_test_break(void)
* \note Don't use MEM_mallocN so functions can be registered at any time.
* \{ */
-struct AtExitData {
+static struct AtExitData {
struct AtExitData *next;
void (*func)(void *user_data);
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 264d87b86f3..5a0006e679f 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -376,6 +376,45 @@ static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *r
}
}
+#define V3_MUL_ELEM(a, b) \
+ (a)[0] * (b)[0], \
+ (a)[1] * (b)[1], \
+ (a)[2] * (b)[2]
+
+/* Callback to bvh tree nearest edge to ray.
+ * The tree must have been built using bvhtree_from_mesh_edges.
+ * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
+static void mesh_edges_nearest_to_ray(
+ void *userdata, const float ray_co[3], const float ray_dir[3],
+ const float scale[3], int index, BVHTreeNearest *nearest)
+{
+ struct BVHTreeFromMesh *data = userdata;
+ const MVert *vert = data->vert;
+ const MEdge *e = &data->edge[index];
+
+ const float t0[3] = {V3_MUL_ELEM(vert[e->v1].co, scale)};
+ const float t1[3] = {V3_MUL_ELEM(vert[e->v2].co, scale)};
+ const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
+ const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
+
+ float depth, point[3];
+ const float dist_sq = dist_squared_ray_to_seg_v3(origin_sc, dir_sc, t0, t1, point, &depth);
+
+ if (dist_sq < nearest->dist_sq) {
+ nearest->dist_sq = dist_sq;
+ nearest->index = index;
+
+ point[0] /= scale[0];
+ point[1] /= scale[1];
+ point[2] /= scale[2];
+
+ copy_v3_v3(nearest->co, point);
+ sub_v3_v3v3(nearest->no, t0, t1);
+ }
+}
+
+#undef V3_MUL_ELEM
+
/** \} */
/*
@@ -393,8 +432,6 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(
BMEditMesh *em, const int verts_num,
const BLI_bitmap *verts_mask, int verts_num_active)
{
- BVHTree *tree = NULL;
- int i;
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
if (verts_mask) {
BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num));
@@ -403,15 +440,14 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(
verts_num_active = verts_num;
}
- tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
+ BVHTree *tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
if (tree) {
- BMIter iter;
- BMVert *eve;
- BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ for (int i = 0; i < verts_num; i++) {
if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
continue;
}
+ BMVert *eve = BM_vert_at_index(em->bm, i);
BLI_bvhtree_insert(tree, i, eve->co, 1);
}
BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active);
@@ -423,31 +459,28 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(
static BVHTree *bvhtree_from_mesh_verts_create_tree(
float epsilon, int tree_type, int axis,
- MVert *vert, const int verts_num,
+ const MVert *vert, const int verts_num,
const BLI_bitmap *verts_mask, int verts_num_active)
{
- BVHTree *tree = NULL;
- int i;
- if (vert) {
- if (verts_mask) {
- BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num));
- }
- else {
- verts_num_active = verts_num;
- }
+ BLI_assert(vert != NULL);
+ if (verts_mask) {
+ BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num));
+ }
+ else {
+ verts_num_active = verts_num;
+ }
- tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
+ BVHTree *tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
- if (tree) {
- for (i = 0; i < verts_num; i++) {
- if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
- continue;
- }
- BLI_bvhtree_insert(tree, i, vert[i].co, 1);
+ if (tree) {
+ for (int i = 0; i < verts_num; i++) {
+ if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
+ continue;
}
- BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active);
- BLI_bvhtree_balance(tree);
+ BLI_bvhtree_insert(tree, i, vert[i].co, 1);
}
+ BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active);
+ BLI_bvhtree_balance(tree);
}
return tree;
@@ -455,31 +488,24 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree(
static void bvhtree_from_mesh_verts_setup_data(
BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon,
- MVert *vert, const bool vert_allocated)
+ const MVert *vert, const bool vert_allocated)
{
memset(data, 0, sizeof(*data));
- if (tree) {
- data->tree = tree;
- data->cached = is_cached;
+ data->tree = tree;
+ data->cached = is_cached;
- /* a NULL nearest callback works fine
- * remember the min distance to point is the same as the min distance to BV of point */
- data->nearest_callback = NULL;
- data->raycast_callback = mesh_verts_spherecast;
- data->nearest_to_ray_callback = NULL;
+ /* a NULL nearest callback works fine
+ * remember the min distance to point is the same as the min distance to BV of point */
+ data->nearest_callback = NULL;
+ data->raycast_callback = mesh_verts_spherecast;
+ data->nearest_to_ray_callback = NULL;
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- //data->face = DM_get_tessface_array(dm, &data->face_allocated); /* XXX WHY???? */
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ //data->face = DM_get_tessface_array(dm, &data->face_allocated); /* XXX WHY???? */
- data->sphere_radius = epsilon;
- }
- else {
- if (vert_allocated) {
- MEM_freeN(vert);
- }
- }
+ data->sphere_radius = epsilon;
}
/* Builds a bvh tree where nodes are the vertices of the given em */
@@ -488,11 +514,9 @@ BVHTree *bvhtree_from_editmesh_verts_ex(
const BLI_bitmap *verts_mask, int verts_num_active,
float epsilon, int tree_type, int axis)
{
- int vert_num = em->bm->totvert;
-
BVHTree *tree = bvhtree_from_editmesh_verts_create_tree(
epsilon, tree_type, axis,
- em, vert_num, verts_mask, verts_num_active);
+ em, em->bm->totvert, verts_mask, verts_num_active);
if (tree) {
memset(data, 0, sizeof(*data));
@@ -505,6 +529,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(
return tree;
}
+
BVHTree *bvhtree_from_editmesh_verts(
BVHTreeFromEditMesh *data, BMEditMesh *em,
float epsilon, int tree_type, int axis)
@@ -515,8 +540,8 @@ BVHTree *bvhtree_from_editmesh_verts(
epsilon, tree_type, axis);
}
-
-/* Builds a bvh tree where nodes are the vertices of the given dm */
+/* Builds a bvh tree where nodes are the vertices of the given dm
+ * and stores the BVHTree in dm->bvhCache */
BVHTree *bvhtree_from_mesh_verts(
BVHTreeFromMesh *data, DerivedMesh *dm,
float epsilon, int tree_type, int axis)
@@ -556,10 +581,18 @@ BVHTree *bvhtree_from_mesh_verts(
/* printf("BVHTree is already build, using cached tree\n"); */
}
- /* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_verts_setup_data(data, tree, true, epsilon, vert, vert_allocated);
-
- return data->tree;
+ if (tree) {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_verts_setup_data(
+ data, tree, true, epsilon, vert, vert_allocated);
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(vert);
+ }
+ memset(data, 0, sizeof(*data));
+ }
+ return tree;
}
/**
@@ -569,7 +602,7 @@ BVHTree *bvhtree_from_mesh_verts(
* \param verts_num_active if >= 0, number of active verts to add to BVH tree (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_verts_ex(
- BVHTreeFromMesh *data, MVert *vert, const int verts_num, const bool vert_allocated,
+ BVHTreeFromMesh *data, const MVert *vert, const int verts_num, const bool vert_allocated,
const BLI_bitmap *verts_mask, int verts_num_active,
float epsilon, int tree_type, int axis)
{
@@ -577,9 +610,10 @@ BVHTree *bvhtree_from_mesh_verts_ex(
epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active);
/* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_verts_setup_data(data, tree, false, epsilon, vert, vert_allocated);
+ bvhtree_from_mesh_verts_setup_data(
+ data, tree, false, epsilon, vert, vert_allocated);
- return data->tree;
+ return tree;
}
/** \} */
@@ -595,8 +629,6 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(
BMEditMesh *em, const int edges_num,
const BLI_bitmap *edges_mask, int edges_num_active)
{
- BVHTree *tree = NULL;
- int i;
BM_mesh_elem_table_ensure(em->bm, BM_EDGE);
if (edges_mask) {
BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edges_num));
@@ -605,9 +637,10 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(
edges_num_active = edges_num;
}
- tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis);
+ BVHTree *tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis);
if (tree) {
+ int i;
BMIter iter;
BMEdge *eed;
BM_ITER_MESH_INDEX (eed, &iter, em->bm, BM_EDGES_OF_MESH, i) {
@@ -627,6 +660,63 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(
return tree;
}
+static BVHTree *bvhtree_from_mesh_edges_create_tree(
+ const MVert *vert, const MEdge *edge, const int edge_num,
+ const BLI_bitmap *edges_mask, int edges_num_active,
+ float epsilon, int tree_type, int axis)
+{
+ if (edges_mask) {
+ BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edge_num));
+ }
+ else {
+ edges_num_active = edge_num;
+ }
+ BLI_assert(vert != NULL);
+ BLI_assert(edge != NULL);
+
+ /* Create a bvh-tree of the given target */
+ BVHTree *tree = BLI_bvhtree_new(edges_num_active, epsilon, tree_type, axis);
+ if (tree) {
+ for (int i = 0; i < edge_num; i++) {
+ if (edges_mask && !BLI_BITMAP_TEST_BOOL(edges_mask, i)) {
+ continue;
+ }
+ float co[2][3];
+ copy_v3_v3(co[0], vert[edge[i].v1].co);
+ copy_v3_v3(co[1], vert[edge[i].v2].co);
+
+ BLI_bvhtree_insert(tree, i, co[0], 2);
+ }
+ BLI_bvhtree_balance(tree);
+ }
+
+ return tree;
+}
+
+static void bvhtree_from_mesh_edges_setup_data(
+ BVHTreeFromMesh *data, BVHTree *tree,
+ const bool is_cached, float epsilon,
+ const MVert *vert, const bool vert_allocated,
+ const MEdge *edge, const bool edge_allocated)
+{
+ memset(data, 0, sizeof(*data));
+
+ data->tree = tree;
+
+ data->cached = is_cached;
+
+ data->nearest_callback = mesh_edges_nearest_point;
+ data->raycast_callback = mesh_edges_spherecast;
+ data->nearest_to_ray_callback = mesh_edges_nearest_to_ray;
+
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->edge = edge;
+ data->edge_allocated = edge_allocated;
+
+ data->sphere_radius = epsilon;
+}
+
/* Builds a bvh tree where nodes are the edges of the given em */
BVHTree *bvhtree_from_editmesh_edges_ex(
BVHTreeFromEditMesh *data, BMEditMesh *em,
@@ -651,6 +741,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(
return tree;
}
+
BVHTree *bvhtree_from_editmesh_edges(
BVHTreeFromEditMesh *data, BMEditMesh *em,
float epsilon, int tree_type, int axis)
@@ -683,27 +774,13 @@ BVHTree *bvhtree_from_mesh_edges(
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
tree = bvhcache_find(dm->bvhCache, BVHTREE_FROM_EDGES);
if (tree == NULL) {
- int i;
- int numEdges = dm->getNumEdges(dm);
-
- if (vert != NULL && edge != NULL) {
- /* Create a bvh-tree of the given target */
- tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis);
- if (tree != NULL) {
- for (i = 0; i < numEdges; i++) {
- float co[2][3];
- copy_v3_v3(co[0], vert[edge[i].v1].co);
- copy_v3_v3(co[1], vert[edge[i].v2].co);
-
- BLI_bvhtree_insert(tree, i, co[0], 2);
- }
- BLI_bvhtree_balance(tree);
+ tree = bvhtree_from_mesh_edges_create_tree(
+ vert, edge, dm->getNumEdges(dm),
+ NULL, -1, epsilon, tree_type, axis);
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES);
- }
- }
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_EDGES);
}
BLI_rw_mutex_unlock(&cache_rwlock);
}
@@ -711,24 +788,10 @@ BVHTree *bvhtree_from_mesh_edges(
/* printf("BVHTree is already build, using cached tree\n"); */
}
-
- /* Setup BVHTreeFromMesh */
- memset(data, 0, sizeof(*data));
- data->tree = tree;
-
- if (data->tree) {
- data->cached = true;
-
- data->nearest_callback = mesh_edges_nearest_point;
- data->raycast_callback = mesh_edges_spherecast;
- data->nearest_to_ray_callback = NULL;
-
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->edge = edge;
- data->edge_allocated = edge_allocated;
-
- data->sphere_radius = epsilon;
+ if (tree) {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_edges_setup_data(
+ data, tree, true, epsilon, vert, vert_allocated, edge, edge_allocated);
}
else {
if (vert_allocated) {
@@ -737,8 +800,33 @@ BVHTree *bvhtree_from_mesh_edges(
if (edge_allocated) {
MEM_freeN(edge);
}
+ memset(data, 0, sizeof(*data));
}
- return data->tree;
+ return tree;
+}
+
+/**
+ * Builds a bvh tree where nodes are the given edges .
+ * \param vert/edge_allocated if true, elem freeing will be done when freeing data.
+ * \param edges_mask if not null, true elements give which vert to add to BVH tree.
+ * \param edges_num_active if >= 0, number of active edges to add to BVH tree (else will be computed from mask).
+ */
+BVHTree *bvhtree_from_mesh_edges_ex(
+ BVHTreeFromMesh *data,
+ const MVert *vert, const bool vert_allocated,
+ const MEdge *edge, const int edges_num, const bool edge_allocated,
+ const BLI_bitmap *edges_mask, int edges_num_active,
+ float epsilon, int tree_type, int axis)
+{
+ BVHTree *tree = bvhtree_from_mesh_edges_create_tree(
+ vert, edge, edges_num, edges_mask, edges_num_active,
+ epsilon, tree_type, axis);
+
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_edges_setup_data(
+ data, tree, false, epsilon, vert, vert_allocated, edge, edge_allocated);
+
+ return tree;
}
/** \} */
@@ -751,7 +839,7 @@ BVHTree *bvhtree_from_mesh_edges(
static BVHTree *bvhtree_from_mesh_faces_create_tree(
float epsilon, int tree_type, int axis,
- MVert *vert, MFace *face, const int faces_num,
+ const MVert *vert, const MFace *face, const int faces_num,
const BLI_bitmap *faces_mask, int faces_num_active)
{
BVHTree *tree = NULL;
@@ -795,34 +883,24 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(
static void bvhtree_from_mesh_faces_setup_data(
BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon,
- MVert *vert, const bool vert_allocated,
- MFace *face, const bool face_allocated)
+ const MVert *vert, const bool vert_allocated,
+ const MFace *face, const bool face_allocated)
{
memset(data, 0, sizeof(*data));
- if (tree) {
- data->tree = tree;
- data->cached = is_cached;
+ data->tree = tree;
+ data->cached = is_cached;
- data->nearest_callback = mesh_faces_nearest_point;
- data->raycast_callback = mesh_faces_spherecast;
- data->nearest_to_ray_callback = NULL;
+ data->nearest_callback = mesh_faces_nearest_point;
+ data->raycast_callback = mesh_faces_spherecast;
+ data->nearest_to_ray_callback = NULL;
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->face = face;
- data->face_allocated = face_allocated;
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->face = face;
+ data->face_allocated = face_allocated;
- data->sphere_radius = epsilon;
- }
- else {
- if (vert_allocated) {
- MEM_freeN(vert);
- }
- if (face_allocated) {
- MEM_freeN(face);
- }
- }
+ data->sphere_radius = epsilon;
}
/* Builds a bvh tree where nodes are the tesselated faces of the given dm */
@@ -865,10 +943,21 @@ BVHTree *bvhtree_from_mesh_faces(
/* printf("BVHTree is already build, using cached tree\n"); */
}
- /* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_faces_setup_data(data, tree, true, epsilon, vert, vert_allocated, face, face_allocated);
-
- return data->tree;
+ if (tree) {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_faces_setup_data(
+ data, tree, true, epsilon, vert, vert_allocated, face, face_allocated);
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(vert);
+ }
+ if (face_allocated) {
+ MEM_freeN(face);
+ }
+ memset(data, 0, sizeof(*data));
+ }
+ return tree;
}
/**
@@ -879,8 +968,8 @@ BVHTree *bvhtree_from_mesh_faces(
* \param numFaces_active if >= 0, number of active faces to add to BVH tree (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_faces_ex(
- BVHTreeFromMesh *data, MVert *vert, const bool vert_allocated,
- MFace *face, const int numFaces, const bool face_allocated,
+ BVHTreeFromMesh *data, const MVert *vert, const bool vert_allocated,
+ const MFace *face, const int numFaces, const bool face_allocated,
const BLI_bitmap *faces_mask, int faces_num_active,
float epsilon, int tree_type, int axis)
{
@@ -890,9 +979,10 @@ BVHTree *bvhtree_from_mesh_faces_ex(
faces_mask, faces_num_active);
/* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_faces_setup_data(data, tree, false, epsilon, vert, vert_allocated, face, face_allocated);
+ bvhtree_from_mesh_faces_setup_data(
+ data, tree, false, epsilon, vert, vert_allocated, face, face_allocated);
- return data->tree;
+ return tree;
}
/** \} */
@@ -1003,34 +1093,21 @@ static void bvhtree_from_mesh_looptri_setup_data(
{
memset(data, 0, sizeof(*data));
- if (tree) {
- data->tree = tree;
- data->cached = is_cached;
+ data->tree = tree;
+ data->cached = is_cached;
- data->nearest_callback = mesh_looptri_nearest_point;
- data->raycast_callback = mesh_looptri_spherecast;
- data->nearest_to_ray_callback = NULL;
+ data->nearest_callback = mesh_looptri_nearest_point;
+ data->raycast_callback = mesh_looptri_spherecast;
+ data->nearest_to_ray_callback = NULL;
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->loop = mloop;
- data->loop_allocated = loop_allocated;
- data->looptri = looptri;
- data->looptri_allocated = looptri_allocated;
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->loop = mloop;
+ data->loop_allocated = loop_allocated;
+ data->looptri = looptri;
+ data->looptri_allocated = looptri_allocated;
- data->sphere_radius = epsilon;
- }
- else {
- if (vert_allocated) {
- MEM_freeN((void *)vert);
- }
- if (loop_allocated) {
- MEM_freeN((void *)mloop);
- }
- if (looptri_allocated) {
- MEM_freeN((void *)looptri);
- }
- }
+ data->sphere_radius = epsilon;
}
/**
@@ -1157,14 +1234,28 @@ BVHTree *bvhtree_from_mesh_looptri(
/* printf("BVHTree is already build, using cached tree\n"); */
}
- /* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_looptri_setup_data(
- data, tree, true, epsilon,
- mvert, vert_allocated,
- mloop, loop_allocated,
- looptri, looptri_allocated);
+ if (tree) {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_looptri_setup_data(
+ data, tree, true, epsilon,
+ mvert, vert_allocated,
+ mloop, loop_allocated,
+ looptri, looptri_allocated);
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(mvert);
+ }
+ if (loop_allocated) {
+ MEM_freeN(mloop);
+ }
+ if (looptri_allocated) {
+ MEM_freeN((void *)looptri);
+ }
+ memset(data, 0, sizeof(*data));
+ }
- return data->tree;
+ return tree;
}
BVHTree *bvhtree_from_mesh_looptri_ex(
@@ -1187,7 +1278,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(
mloop, loop_allocated,
looptri, looptri_allocated);
- return data->tree;
+ return tree;
}
/** \} */
@@ -1207,29 +1298,27 @@ void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data)
/* Frees data allocated by a call to bvhtree_from_mesh_*. */
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
{
- if (data->tree) {
- if (!data->cached) {
- BLI_bvhtree_free(data->tree);
- }
-
- if (data->vert_allocated) {
- MEM_freeN((void *)data->vert);
- }
- if (data->edge_allocated) {
- MEM_freeN((void *)data->edge);
- }
- if (data->face_allocated) {
- MEM_freeN((void *)data->face);
- }
- if (data->loop_allocated) {
- MEM_freeN((void *)data->loop);
- }
- if (data->looptri_allocated) {
- MEM_freeN((void *)data->looptri);
- }
+ if (data->tree && !data->cached) {
+ BLI_bvhtree_free(data->tree);
+ }
- memset(data, 0, sizeof(*data));
+ if (data->vert_allocated) {
+ MEM_freeN((void *)data->vert);
}
+ if (data->edge_allocated) {
+ MEM_freeN((void *)data->edge);
+ }
+ if (data->face_allocated) {
+ MEM_freeN((void *)data->face);
+ }
+ if (data->loop_allocated) {
+ MEM_freeN((void *)data->loop);
+ }
+ if (data->looptri_allocated) {
+ MEM_freeN((void *)data->looptri);
+ }
+
+ memset(data, 0, sizeof(*data));
}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index fc3e358cb25..7042b46330b 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -2398,13 +2398,16 @@ DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, const bool use_mdisps, const bo
use_tessface, em->tottri, (const BMLoop *(*)[3])em->looptris);
}
-static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces)
+static DerivedMesh *cddm_copy_ex(DerivedMesh *source,
+ const bool need_tessface_data,
+ const bool faces_from_tessfaces)
{
+ const bool copy_tessface_data = (faces_from_tessfaces || need_tessface_data);
CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
DerivedMesh *dm = &cddm->dm;
int numVerts = source->numVertData;
int numEdges = source->numEdgeData;
- int numTessFaces = source->numTessFaceData;
+ int numTessFaces = copy_tessface_data ? source->numTessFaceData : 0;
int numLoops = source->numLoopData;
int numPolys = source->numPolyData;
@@ -2414,20 +2417,29 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces)
source->getVertDataArray(source, CD_ORIGINDEX);
source->getEdgeDataArray(source, CD_ORIGINDEX);
source->getPolyDataArray(source, CD_ORIGINDEX);
+ if (copy_tessface_data) {
+ source->getTessFaceDataArray(source, CD_ORIGINDEX);
+ }
/* this initializes dm, and copies all non mvert/medge/mface layers */
- DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges,
- faces_from_tessfaces ? numTessFaces : 0,
+ DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces,
numLoops, numPolys);
dm->deformedOnly = source->deformedOnly;
dm->cd_flag = source->cd_flag;
dm->dirty = source->dirty;
- /* Tessellation data is never copied, so tag it here. */
- dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
+ /* Tessellation data is never copied, so tag it here.
+ * Only tag dirty layers if we really ignored tessellation faces.
+ */
+ if (!copy_tessface_data) {
+ dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
+ }
CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
+ if (copy_tessface_data) {
+ CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces);
+ }
/* now add mvert/medge/mface layers */
cddm->mvert = source->dupVertArray(source);
@@ -2435,17 +2447,16 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces)
CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
-
- if (!faces_from_tessfaces) {
- DM_DupPolys(source, dm);
- }
- else {
- source->getTessFaceDataArray(source, CD_ORIGINDEX);
- CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces);
+ if (faces_from_tessfaces || copy_tessface_data) {
cddm->mface = source->dupTessFaceArray(source);
CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces);
+ }
+ if (!faces_from_tessfaces) {
+ DM_DupPolys(source, dm);
+ }
+ else {
CDDM_tessfaces_to_faces(dm);
}
@@ -2457,12 +2468,17 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces)
DerivedMesh *CDDM_copy(DerivedMesh *source)
{
- return cddm_copy_ex(source, 0);
+ return cddm_copy_ex(source, false, false);
}
DerivedMesh *CDDM_copy_from_tessface(DerivedMesh *source)
{
- return cddm_copy_ex(source, 1);
+ return cddm_copy_ex(source, false, true);
+}
+
+DerivedMesh *CDDM_copy_with_tessface(DerivedMesh *source)
+{
+ return cddm_copy_ex(source, true, false);
}
/* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 98d37fb07bf..c9f0b8ec9ca 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -2595,7 +2595,7 @@ bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, Custom
if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT))
return false;
-#undef TEST_RET
+#undef LAYER_CMP
/* if no layers are on either CustomData's,
* then there was nothing to do... */
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index a2d94ccc478..318f6480aaf 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -3159,7 +3159,7 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons
struct ImBuf *ibuf;
char name[FILE_MAX];
int flag;
- ImageUser iuser_t;
+ ImageUser iuser_t = {0};
/* XXX temp stuff? */
if (ima->lastframe != frame)
@@ -3167,8 +3167,12 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons
ima->lastframe = frame;
- if (iuser)
+ if (iuser) {
iuser_t = *iuser;
+ }
+ else {
+ /* TODO(sergey): Do we need to initialize something here? */
+ }
iuser_t.view = view_id;
BKE_image_user_file_path(&iuser_t, ima, name);
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index d098366aef4..69a2067f4e6 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -174,15 +174,10 @@ void BKE_lamp_make_local(Main *bmain, Lamp *la, const bool lib_local)
void BKE_lamp_free(Lamp *la)
{
- MTex *mtex;
int a;
for (a = 0; a < MAX_MTEX; a++) {
- mtex = la->mtex[a];
- if (mtex && mtex->tex)
- id_us_min(&mtex->tex->id);
- if (mtex)
- MEM_freeN(mtex);
+ MEM_SAFE_FREE(la->mtex[a]);
}
BKE_animdata_free((ID *)la, false);
@@ -193,6 +188,7 @@ void BKE_lamp_free(Lamp *la)
if (la->nodetree) {
ntreeFreeTree(la->nodetree);
MEM_freeN(la->nodetree);
+ la->nodetree = NULL;
}
BKE_previewimg_free(&la->preview);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index af02e02b017..24a01b17e53 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -66,6 +66,11 @@
#include "DEG_depsgraph.h"
+/* Define for cases when you want extra validation of mesh
+ * after certain modifications.
+ */
+// #undef VALIDATE_MESH
+
enum {
MESHCMP_DVERT_WEIGHTMISMATCH = 1,
MESHCMP_DVERT_GROUPMISMATCH,
@@ -2090,104 +2095,296 @@ void BKE_mesh_calc_normals_split(Mesh *mesh)
}
}
-/* Spli faces based on the edge angle.
- * Matches behavior of face splitting in render engines.
+/* Split faces helper functions. */
+
+enum {
+ /* Vertex is adjacent to some loop which normal is different,
+ * hence split of this vertex is required.
+ */
+ SPLIT_VERT_NEED_SPLIT = (1 << 0),
+ /* Original vertex was already re-used by split logic. */
+ SPLIT_VERT_REUSED = (1 << 1),
+};
+enum {
+ /* Edge is adjacent to any of vertex tagged for split.
+ */
+ SPLIT_EDGE_NEED_SPLIT = (1 << 0),
+ /* Original edge was already re-used by split logic. */
+ SPLIT_EDGE_REUSED = (1 << 1),
+};
+
+/* Tag vertices which normals are not equal to any adjacent loop
+ * and hence split on that vertex is required.
+ *
+ * Returns truth if any of vertex needs to be split.
*/
-void BKE_mesh_split_faces(Mesh *mesh)
+static bool split_faces_tag_verts(const Mesh *mesh, uchar *vert_flags)
+{
+ const int num_polys = mesh->totpoly;
+ const MVert *mvert = mesh->mvert;
+ const MLoop *mloop = mesh->mloop;
+ const MPoly *mpoly = mesh->mpoly;
+ float (*lnors)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+ bool has_split_verts = false;
+ for (int poly = 0; poly < num_polys; poly++) {
+ const MPoly *mp = &mpoly[poly];
+ for (int loop = 0; loop < mp->totloop; loop++) {
+ const MLoop *ml = &mloop[mp->loopstart + loop];
+ const MVert *mv = &mvert[ml->v];
+ float vn[3];
+ normal_short_to_float_v3(vn, mv->no);
+ if (len_squared_v3v3(vn, lnors[mp->loopstart + loop]) > FLT_EPSILON) {
+ vert_flags[ml->v] |= SPLIT_VERT_NEED_SPLIT;
+ has_split_verts = true;
+ }
+ }
+ }
+ return has_split_verts;
+}
+
+/* Count number of new vertices to be added.
+ *
+ * Note that one of the loop where split is required will re-use
+ * it's vertex in order to avoid creation of loose vertices.
+ */
+static int split_faces_count_new_verts(const Mesh *mesh, uchar *vert_flags)
+{
+ const int num_polys = mesh->totpoly;
+ const MLoop *mloop = mesh->mloop;
+ const MPoly *mpoly = mesh->mpoly;
+ int num_new_verts = 0;
+ for (int poly = 0; poly < num_polys; poly++) {
+ const MPoly *mp = &mpoly[poly];
+ for (int loop = 0; loop < mp->totloop; loop++) {
+ const MLoop *ml = &mloop[mp->loopstart + loop];
+ if (vert_flags[ml->v] & SPLIT_VERT_NEED_SPLIT) {
+ if (vert_flags[ml->v] & SPLIT_VERT_REUSED) {
+ ++num_new_verts;
+ }
+ else {
+ vert_flags[ml->v] |= SPLIT_VERT_REUSED;
+ }
+ }
+ }
+ }
+ return num_new_verts;
+}
+
+/* Tag edges which are adjacent to at least one vertex tagged for split. */
+static void split_faces_tag_edges(Mesh *mesh,
+ const uchar *vert_flags,
+ uchar *edge_flags)
+{
+ const int num_polys = mesh->totpoly;
+ const MLoop *mloop = mesh->mloop;
+ const MPoly *mpoly = mesh->mpoly;
+ for (int poly = 0; poly < num_polys; poly++) {
+ const MPoly *mp = &mpoly[poly];
+ int loop_prev = mp->totloop - 1;
+ for (int loop = 0; loop < mp->totloop; loop++) {
+ const int poly_loop_prev = mp->loopstart + loop_prev;
+ const MLoop *ml = &mloop[mp->loopstart + loop];
+ const MLoop *ml_prev = &mloop[poly_loop_prev];
+ const int mv_flag = vert_flags[ml->v];
+ const int mv_prev_flag = vert_flags[ml_prev->v];
+ bool need_split = false;
+ if (mv_flag & SPLIT_VERT_NEED_SPLIT) {
+ if (mv_prev_flag & SPLIT_VERT_NEED_SPLIT) {
+ /* Create new edge between twp split vertices. */
+ need_split = true;
+ }
+ else {
+ /* Create new edge from existing vertex to a split one. */
+ need_split = true;
+ }
+ }
+ else if (mv_prev_flag & SPLIT_VERT_NEED_SPLIT) {
+ /* Create new edge from split vertex to existing one. */
+ need_split = true;
+ }
+ if (need_split) {
+ edge_flags[ml_prev->e] |= SPLIT_EDGE_NEED_SPLIT;
+ }
+ loop_prev = loop;
+ }
+ }
+}
+
+/* Count number of new edges to be added.
+ *
+ * Note that one of the loop where split is required will re-use
+ * it's edge in order to avoid creation of loose edges.
+ */
+static int split_faces_count_new_edges(const Mesh *mesh, uchar *edge_flags)
{
- const int num_verts = mesh->totvert;
- const int num_edges = mesh->totedge;
+ const int num_polys = mesh->totpoly;
+ const MLoop *mloop = mesh->mloop;
+ const MPoly *mpoly = mesh->mpoly;
+ int num_new_edges = 0;
+ for (int poly = 0; poly < num_polys; poly++) {
+ const MPoly *mp = &mpoly[poly];
+ for (int loop = 0; loop < mp->totloop; loop++) {
+ const MLoop *ml = &mloop[mp->loopstart + loop];
+ if (edge_flags[ml->e] & SPLIT_EDGE_NEED_SPLIT) {
+ if (edge_flags[ml->e] & SPLIT_EDGE_REUSED) {
+ ++num_new_edges;
+ }
+ else {
+ edge_flags[ml->e] |= SPLIT_EDGE_REUSED;
+ }
+ }
+ }
+ }
+ return num_new_edges;
+}
+
+/* Perform actual split of vertices.
+ *
+ * NOTE: Will leave edges in inconsistent state.
+ */
+static void split_faces_split_verts(Mesh *mesh,
+ const int num_new_verts,
+ uchar *vert_flags)
+{
+ const int num_verts = mesh->totvert - num_new_verts;
const int num_polys = mesh->totpoly;
MVert *mvert = mesh->mvert;
+ MLoop *mloop = mesh->mloop;
+ MPoly *mpoly = mesh->mpoly;
+ const float (*lnors)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+ int num_added_verts = 0;
+ /* Clear reused flag, we need it again. */
+ for (int i = 0; i < num_verts; ++i) {
+ vert_flags[i] &= ~SPLIT_VERT_REUSED;
+ }
+ for (int poly = 0; poly < num_polys; poly++) {
+ MPoly *mp = &mpoly[poly];
+ /* First we split all vertices to get proper flag whether they are
+ * split or not for all of them before handling edges.
+ */
+ for (int loop = 0; loop < mp->totloop; loop++) {
+ int poly_loop = mp->loopstart + loop;
+ MLoop *ml = &mloop[poly_loop];
+ if (vert_flags[ml->v] & SPLIT_VERT_NEED_SPLIT) {
+ if ((vert_flags[ml->v] & SPLIT_VERT_REUSED) == 0) {
+ /* Ignore first split on vertex, re-use it instead. */
+ vert_flags[ml->v] |= SPLIT_VERT_REUSED;
+ continue;
+ }
+ /* Create new vertex. */
+ int new_vert = num_verts + num_added_verts;
+ CustomData_copy_data(&mesh->vdata, &mesh->vdata,
+ ml->v, new_vert, 1);
+ normal_float_to_short_v3(mvert[new_vert].no,
+ lnors[poly_loop]);
+ ml->v = new_vert;
+ num_added_verts++;
+ }
+ }
+ }
+}
+
+/* Perform actual split of edges.
+ *
+ * NOTE: Will correct all edges.
+ */
+static void split_faces_split_edges(Mesh *mesh,
+ const int num_new_edges,
+ uchar *edge_flags)
+{
+ const int num_edges = mesh->totedge - num_new_edges;
+ const int num_polys = mesh->totpoly;
MEdge *medge = mesh->medge;
MLoop *mloop = mesh->mloop;
MPoly *mpoly = mesh->mpoly;
- float (*lnors)[3];
- int poly, num_new_verts = 0;
+ int num_added_edges = 0;
+ /* Clear reused flag, we need it again. */
+ for (int i = 0; i < num_edges; ++i) {
+ edge_flags[i] &= ~SPLIT_EDGE_REUSED;
+ }
+ for (int poly = 0; poly < num_polys; poly++) {
+ MPoly *mp = &mpoly[poly];
+ for (int loop = 0, loop_prev = mp->totloop - 1; loop < mp->totloop; loop++) {
+ const int poly_loop_prev = mp->loopstart + loop_prev;
+ const MLoop *ml = &mloop[mp->loopstart + loop];
+ MLoop *ml_prev = &mloop[poly_loop_prev];
+ MEdge *me_prev = &medge[ml_prev->e];
+ if (edge_flags[ml_prev->e] & SPLIT_EDGE_NEED_SPLIT) {
+ if ((edge_flags[ml_prev->e] & SPLIT_EDGE_REUSED) == 0) {
+ edge_flags[ml_prev->e] |= SPLIT_EDGE_REUSED;
+ me_prev->v1 = ml_prev->v;
+ me_prev->v2 = ml->v;
+ }
+ else {
+ const int index = num_edges + num_added_edges;
+ CustomData_copy_data(&mesh->edata, &mesh->edata,
+ ml_prev->e, index, 1);
+ MEdge *me_new = &medge[index];
+ me_new->v1 = ml_prev->v;
+ me_new->v2 = ml->v;
+ ml_prev->e = index;
+ num_added_edges++;
+ }
+ }
+ loop_prev = loop;
+ }
+ }
+}
+
+/* Split faces based on the edge angle.
+ * Matches behavior of face splitting in render engines.
+ */
+void BKE_mesh_split_faces(Mesh *mesh)
+{
+ const int num_verts = mesh->totvert;
+ const int num_edges = mesh->totedge;
+ const int num_polys = mesh->totpoly;
if ((mesh->flag & ME_AUTOSMOOTH) == 0) {
return;
}
+ if (num_polys == 0) {
+ return;
+ }
BKE_mesh_tessface_clear(mesh);
/* Compute loop normals if needed. */
if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(mesh);
}
- lnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
- /* Count number of vertices to be split. */
- for (poly = 0; poly < num_polys; poly++) {
- MPoly *mp = &mpoly[poly];
- int loop;
- for (loop = 0; loop < mp->totloop; loop++) {
- MLoop *ml = &mloop[mp->loopstart + loop];
- MVert *mv = &mvert[ml->v];
- float vn[3];
- normal_short_to_float_v3(vn, mv->no);
- if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) {
- num_new_verts++;
- }
- }
- }
- if (num_new_verts == 0) {
- /* No new vertices are to be added, can do early exit. */
+ /* Runtime flags. */
+ uchar *vert_flags = MEM_callocN(sizeof(*vert_flags) * num_verts,
+ "split faces vert flags");
+ /* Tag vertces and check whether anything is tagged. */
+ if (!split_faces_tag_verts(mesh, vert_flags)) {
+ /* No new vertices to be split added, can do early exit. */
+ MEM_freeN(vert_flags);
return;
}
+ /* Flush vertex flags to edges. */
+ uchar *edge_flags = MEM_callocN(sizeof(*edge_flags) * num_edges,
+ "split faces edge flags");
+ split_faces_tag_edges(mesh, vert_flags, edge_flags);
+ /* Count amount of new geometry. */
+ int num_new_verts = split_faces_count_new_verts(mesh, vert_flags);
+ int num_new_edges = split_faces_count_new_edges(mesh, edge_flags);
/* Reallocate all vert and edge related data. */
mesh->totvert += num_new_verts;
- mesh->totedge += 2 * num_new_verts;
+ mesh->totedge += num_new_edges;
CustomData_realloc(&mesh->vdata, mesh->totvert);
CustomData_realloc(&mesh->edata, mesh->totedge);
/* Update pointers to a newly allocated memory. */
BKE_mesh_update_customdata_pointers(mesh, false);
- mvert = mesh->mvert;
- medge = mesh->medge;
- /* Perform actual vertex split. */
- num_new_verts = 0;
- for (poly = 0; poly < num_polys; poly++) {
- MPoly *mp = &mpoly[poly];
- int loop;
- for (loop = 0; loop < mp->totloop; loop++) {
- int poly_loop = mp->loopstart + loop;
- MLoop *ml = &mloop[poly_loop];
- MVert *mv = &mvert[ml->v];
- float vn[3];
- normal_short_to_float_v3(vn, mv->no);
- if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) {
- int poly_loop_prev = mp->loopstart + (loop + mp->totloop - 1) % mp->totloop;
- MLoop *ml_prev = &mloop[poly_loop_prev];
- int new_edge_prev, new_edge;
- /* Cretae new vertex. */
- int new_vert = num_verts + num_new_verts;
- CustomData_copy_data(&mesh->vdata, &mesh->vdata,
- ml->v, new_vert, 1);
- normal_float_to_short_v3(mvert[new_vert].no,
- lnors[poly_loop]);
- /* Create new edges. */
- new_edge_prev = num_edges + 2 * num_new_verts;
- new_edge = num_edges + 2 * num_new_verts + 1;
- CustomData_copy_data(&mesh->edata, &mesh->edata,
- ml_prev->e, new_edge_prev, 1);
- CustomData_copy_data(&mesh->edata, &mesh->edata,
- ml->e, new_edge, 1);
- if (medge[new_edge_prev].v1 == ml->v) {
- medge[new_edge_prev].v1 = new_vert;
- }
- else {
- medge[new_edge_prev].v2 = new_vert;
- }
- if (medge[new_edge].v1 == ml->v) {
- medge[new_edge].v1 = new_vert;
- }
- else {
- medge[new_edge].v2 = new_vert;
- }
-
- ml->v = new_vert;
- ml_prev->e = new_edge_prev;
- ml->e = new_edge;
- num_new_verts++;
- }
- }
- }
+ /* Perform actual split of vertices and adjacent edges. */
+ split_faces_split_verts(mesh, num_new_verts, vert_flags);
+ split_faces_split_edges(mesh, num_new_edges, edge_flags);
+ /* CD_NORMAL is expected to be temporary only, and it's invalid at
+ * this point anyway.
+ */
+ CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
+ MEM_freeN(vert_flags);
+ MEM_freeN(edge_flags);
+#ifdef VALIDATE_MESH
+ BKE_mesh_validate(mesh, true, true);
+#endif
}
/* settings: 1 - preview, 2 - render */
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index ff8be5892e9..6e754755cf3 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2236,66 +2236,6 @@ void BKE_boundbox_minmax(const BoundBox *bb, float obmat[4][4], float r_min[3],
}
}
-/**
- * Returns a BBox which each dimensions are at least epsilon.
- * \note In case a given dimension needs to be enlarged, its final value will be in [epsilon, 3 * epsilon] range.
- *
- * \param bb the input bbox to check.
- * \param bb_temp the temp bbox to modify (\a bb content is never changed).
- * \param epsilon the minimum dimension to ensure.
- * \return either bb (if nothing needed to be changed) or bb_temp.
- */
-BoundBox *BKE_boundbox_ensure_minimum_dimensions(BoundBox *bb, BoundBox *bb_temp, const float epsilon)
-{
- if (fabsf(bb->vec[0][0] - bb->vec[4][0]) < epsilon) {
- /* Flat along X axis... */
- *bb_temp = *bb;
- bb = bb_temp;
- bb->vec[0][0] -= epsilon;
- bb->vec[1][0] -= epsilon;
- bb->vec[2][0] -= epsilon;
- bb->vec[3][0] -= epsilon;
- bb->vec[4][0] += epsilon;
- bb->vec[5][0] += epsilon;
- bb->vec[6][0] += epsilon;
- bb->vec[7][0] += epsilon;
- }
-
- if (fabsf(bb->vec[0][1] - bb->vec[3][1]) < epsilon) {
- /* Flat along Y axis... */
- if (bb != bb_temp) {
- *bb_temp = *bb;
- bb = bb_temp;
- }
- bb->vec[0][1] -= epsilon;
- bb->vec[1][1] -= epsilon;
- bb->vec[4][1] -= epsilon;
- bb->vec[5][1] -= epsilon;
- bb->vec[2][1] += epsilon;
- bb->vec[3][1] += epsilon;
- bb->vec[6][1] += epsilon;
- bb->vec[7][1] += epsilon;
- }
-
- if (fabsf(bb->vec[0][2] - bb->vec[1][2]) < epsilon) {
- /* Flat along Z axis... */
- if (bb != bb_temp) {
- *bb_temp = *bb;
- bb = bb_temp;
- }
- bb->vec[0][2] -= epsilon;
- bb->vec[3][2] -= epsilon;
- bb->vec[4][2] -= epsilon;
- bb->vec[7][2] -= epsilon;
- bb->vec[1][2] += epsilon;
- bb->vec[2][2] += epsilon;
- bb->vec[5][2] += epsilon;
- bb->vec[6][2] += epsilon;
- }
-
- return bb;
-}
-
BoundBox *BKE_object_boundbox_get(Object *ob)
{
BoundBox *bb = NULL;
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 1ea27558545..228ae6afaba 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -633,8 +633,9 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], floa
data->childcachebufs.last = psys->childcachebufs.last;
data->totchildcache = psys->totchildcache;
- if (psmd->dm_final)
- data->dm = CDDM_copy(psmd->dm_final);
+ if (psmd->dm_final) {
+ data->dm = CDDM_copy_with_tessface(psmd->dm_final);
+ }
data->totdmvert = psmd->totdmvert;
data->totdmedge = psmd->totdmedge;
data->totdmface = psmd->totdmface;
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 1d2f5aee440..6a491ba5ec4 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -480,55 +480,74 @@ void BKE_sequencer_editing_free(Scene *scene)
static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf)
{
- if (ibuf->rect_float) {
+ if (ibuf->rect != NULL) {
+ IMB_colormanagement_assign_rect_colorspace(ibuf, scene->sequencer_colorspace_settings.name);
+ }
+ if (ibuf->rect_float != NULL) {
IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name);
}
}
void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make_float)
{
- const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR);
+ /* Early output check: if both buffers are NULL we have nothing to convert. */
+ if (ibuf->rect_float == NULL && ibuf->rect == NULL) {
+ return;
+ }
+ /* Get common conversion settings. */
const char *to_colorspace = scene->sequencer_colorspace_settings.name;
- const char *float_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
-
- if (!ibuf->rect_float) {
- if (ibuf->rect) {
- const char *byte_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
- if (make_float || !STREQ(to_colorspace, byte_colorspace)) {
- /* If byte space is not in sequencer's working space, we deliver float color space,
- * this is to to prevent data loss.
- */
-
- /* when converting byte buffer to float in sequencer we need to make float
- * buffer be in sequencer's working space, which is currently only doable
- * from linear space.
- */
-
- /*
- * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's
- */
-
- IMB_float_from_rect(ibuf);
- }
- else {
- return;
- }
+ /* Perform actual conversion logic. */
+ if (ibuf->rect_float == NULL) {
+ /* We are not requested to give float buffer and byte buffer is already
+ * in thee required colorspace. Can skip doing anything here.
+ */
+ const char *from_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf);
+ if (!make_float && STREQ(from_colorspace, to_colorspace)) {
+ return;
+ }
+ if (false) {
+ /* The idea here is to provide as fast playback as possible and
+ * enforcing float buffer here (a) uses more cache memory (b) might
+ * make some other effects slower to apply.
+ *
+ * However, this might also have negative effect by adding weird
+ * artifacts which will then not happen in final render.
+ */
+ IMB_colormanagement_transform_byte_threaded(
+ (unsigned char*)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels,
+ from_colorspace, to_colorspace);
}
else {
- return;
+ /* We perform conversion to a float buffer so we don't worry about
+ * precision loss.
+ */
+ imb_addrectfloatImBuf(ibuf);
+ IMB_colormanagement_transform_from_byte_threaded(
+ ibuf->rect_float, (unsigned char*)ibuf->rect,
+ ibuf->x, ibuf->y, ibuf->channels,
+ from_colorspace, to_colorspace);
+ /* We don't need byte buffer anymore. */
+ imb_freerectImBuf(ibuf);
}
}
-
- if (from_colorspace && from_colorspace[0] != '\0') {
- if (ibuf->rect)
+ else {
+ const char *from_colorspace = IMB_colormanagement_get_float_colorspace(ibuf);
+ /* Unknown input color space, can't perform conversion. */
+ if (from_colorspace == NULL || from_colorspace[0] == '\0') {
+ return;
+ }
+ /* We don't want both byte and float buffers around: they'll either run
+ * out of sync or conversion of byte buffer will loose precision in there.
+ */
+ if (ibuf->rect != NULL) {
imb_freerectImBuf(ibuf);
-
- if (!STREQ(float_colorspace, to_colorspace)) {
- IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels,
- from_colorspace, to_colorspace, true);
- sequencer_imbuf_assign_spaces(scene, ibuf);
}
+ IMB_colormanagement_transform_threaded(ibuf->rect_float,
+ ibuf->x, ibuf->y, ibuf->channels,
+ from_colorspace, to_colorspace,
+ true);
}
+ sequencer_imbuf_assign_spaces(scene, ibuf);
}
void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf)
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 22288127119..8469351c54a 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -147,12 +147,12 @@ void BKE_sound_free(bSound *sound)
BKE_sound_free_waveform(sound);
+#endif /* WITH_AUDASPACE */
if (sound->spinlock) {
BLI_spin_end(sound->spinlock);
MEM_freeN(sound->spinlock);
sound->spinlock = NULL;
- }
-#endif /* WITH_AUDASPACE */
+ }
}
void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local)
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 88575c7d3be..298790a9e9b 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -1935,7 +1935,7 @@ void txt_do_undo(Text *text)
int op = text->undo_buf[text->undo_pos];
int prev_flags;
unsigned int linep;
- unsigned int uchar;
+ unsigned int uni_char;
unsigned int curln, selln;
unsigned short curc, selc;
unsigned short charp;
@@ -1971,14 +1971,14 @@ void txt_do_undo(Text *text)
case UNDO_BS_3:
case UNDO_BS_4:
charp = op - UNDO_BS_1 + 1;
- uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
/* get and restore the cursors */
txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- txt_add_char(text, uchar);
+ txt_add_char(text, uni_char);
text->undo_pos--;
break;
@@ -1988,14 +1988,14 @@ void txt_do_undo(Text *text)
case UNDO_DEL_3:
case UNDO_DEL_4:
charp = op - UNDO_DEL_1 + 1;
- uchar = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
/* get and restore the cursors */
txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- txt_add_char(text, uchar);
+ txt_add_char(text, uni_char);
txt_move_left(text, 0);
@@ -2163,7 +2163,7 @@ void txt_do_redo(Text *text)
char *buf;
unsigned int linep;
unsigned short charp;
- unsigned int uchar;
+ unsigned int uni_uchar;
unsigned int curln, selln;
unsigned short curc, selc;
@@ -2190,9 +2190,9 @@ void txt_do_redo(Text *text)
txt_move_to(text, curln, curc, 1);
charp = op - UNDO_INSERT_1 + 1;
- uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp);
- txt_add_char(text, uchar);
+ txt_add_char(text, uni_uchar);
break;
case UNDO_BS_1:
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 2d3ecad19ad..60990c03b0e 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -1485,9 +1485,11 @@ bool BKE_texture_dependsOnTime(const struct Tex *texture)
/* ------------------------------------------------------------------------- */
-void BKE_texture_get_value(
+void BKE_texture_get_value_ex(
const Scene *scene, Tex *texture,
- float *tex_co, TexResult *texres, bool use_color_management)
+ float *tex_co, TexResult *texres,
+ struct ImagePool *pool,
+ bool use_color_management)
{
int result_type;
bool do_color_manage = false;
@@ -1497,7 +1499,7 @@ void BKE_texture_get_value(
}
/* no node textures for now */
- result_type = multitex_ext_safe(texture, tex_co, texres, NULL, do_color_manage, false);
+ result_type = multitex_ext_safe(texture, tex_co, texres, pool, do_color_manage, false);
/* if the texture gave an RGB value, we assume it didn't give a valid
* intensity, since this is in the context of modifiers don't use perceptual color conversion.
@@ -1510,3 +1512,10 @@ void BKE_texture_get_value(
copy_v3_fl(&texres->tr, texres->tin);
}
}
+
+void BKE_texture_get_value(
+ const Scene *scene, Tex *texture,
+ float *tex_co, TexResult *texres, bool use_color_management)
+{
+ BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management);
+}
diff --git a/source/blender/blenlib/BLI_dynlib.h b/source/blender/blenlib/BLI_dynlib.h
index 7d5eb888021..310db9ea051 100644
--- a/source/blender/blenlib/BLI_dynlib.h
+++ b/source/blender/blenlib/BLI_dynlib.h
@@ -34,7 +34,7 @@
typedef struct DynamicLibrary DynamicLibrary;
-DynamicLibrary *BLI_dynlib_open(char *name);
+DynamicLibrary *BLI_dynlib_open(const char *name);
void *BLI_dynlib_find_symbol(DynamicLibrary *lib, const char *symname);
char *BLI_dynlib_get_error_as_string(DynamicLibrary *lib);
void BLI_dynlib_close(DynamicLibrary *lib);
diff --git a/source/blender/blenlib/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h
index 7929e1d6551..9d8222c575d 100644
--- a/source/blender/blenlib/BLI_sys_types.h
+++ b/source/blender/blenlib/BLI_sys_types.h
@@ -80,6 +80,11 @@ typedef uint64_t u_int64_t;
#include <stddef.h> /* size_t define */
#include <stdbool.h>
+typedef unsigned int uint;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+typedef unsigned char uchar;
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/PIL_time_utildefines.h b/source/blender/blenlib/PIL_time_utildefines.h
index 9157e04a7bf..412cfb3a090 100644
--- a/source/blender/blenlib/PIL_time_utildefines.h
+++ b/source/blender/blenlib/PIL_time_utildefines.h
@@ -80,9 +80,10 @@
} \
const float _delta_##var = TIMEIT_VALUE(var); \
_sum_##var += _delta_##var; \
+ _num_##var++; \
printf("time end (" #var "): %.6f" " " AT "\n", _delta_##var); \
- printf("time averaged (" #var "): %.6f" " " AT "\n", \
- (_sum_##var / ++_num_##var)); \
+ printf("time averaged (" #var "): %.6f (total: %.6f, in %d runs)\n", \
+ (_sum_##var / _num_##var), _sum_##var, (int)_num_##var); \
fflush(stdout); \
} (void)0
diff --git a/source/blender/blenlib/intern/dynlib.c b/source/blender/blenlib/intern/dynlib.c
index b47c2ee60a6..51b91fb360f 100644
--- a/source/blender/blenlib/intern/dynlib.c
+++ b/source/blender/blenlib/intern/dynlib.c
@@ -50,7 +50,7 @@ struct DynamicLibrary {
#include "utf_winfunc.h"
#include "utfconv.h"
-DynamicLibrary *BLI_dynlib_open(char *name)
+DynamicLibrary *BLI_dynlib_open(const char *name)
{
DynamicLibrary *lib;
void *handle;
@@ -106,7 +106,7 @@ void BLI_dynlib_close(DynamicLibrary *lib)
#include <dlfcn.h>
-DynamicLibrary *BLI_dynlib_open(char *name)
+DynamicLibrary *BLI_dynlib_open(const char *name)
{
DynamicLibrary *lib;
void *handle = dlopen(name, RTLD_LAZY);
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c
index 8d9881e4539..2969b0eccf4 100644
--- a/source/blender/blenlib/intern/polyfill2d.c
+++ b/source/blender/blenlib/intern/polyfill2d.c
@@ -21,8 +21,15 @@
/** \file blender/blenlib/intern/polyfill2d.c
* \ingroup bli
*
- * A simple implementation of the ear cutting algorithm
- * to triangulate simple polygons without holes.
+ * An ear clipping algorithm to triangulate single boundary polygons.
+ *
+ * Details:
+ *
+ * - The algorithm guarantees all triangles are assigned (number of coords - 2)
+ * and that triangles will have non-overlapping indices (even for degenerate geometry).
+ * - Self-intersections are considered degenerate (resulting triangles will overlap).
+ * - While multiple polygons aren't supported, holes can still be defined using *key-holes*
+ * (where the polygon doubles back on its self with *exactly* matching coordinates).
*
* \note
*
@@ -74,6 +81,12 @@ typedef signed char eSign;
#ifdef USE_KDTREE
/**
+ * Spatial optimization for point-in-triangle intersection checks.
+ * The simple version of this algorithm is ``O(n^2)`` complexity
+ * (every point needing to check the triangle defined by every other point),
+ * Using a binary-tree reduces the complexity to ``O(n log n)``
+ * plus some overhead of creating the tree.
+ *
* This is a single purpose KDTree based on BLI_kdtree with some modifications
* to better suit polyfill2d.
*
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 6264336c096..7ea79fc5557 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -10395,6 +10395,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
else {
mainptr->curlib->filedata = NULL;
mainptr->curlib->id.tag |= LIB_TAG_MISSING;
+ /* Set lib version to current main one... Makes assert later happy. */
+ mainptr->versionfile = mainptr->curlib->versionfile = mainl->versionfile;
+ mainptr->subversionfile = mainptr->curlib->subversionfile = mainl->subversionfile;
}
if (fd == NULL) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 7b8b95f0005..998d4161c2f 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -78,7 +78,7 @@
* - write #TEST (#RenderInfo struct. 128x128 blend file preview is optional).
* - write #GLOB (#FileGlobal struct) (some global vars).
* - write #DNA1 (#SDNA struct)
- * - write #USER (#UserDef struct) if filename is ``~/X.XX/config/startup.blend``.
+ * - write #USER (#UserDef struct) if filename is ``~/.config/blender/X.XX/config/startup.blend``.
*/
@@ -799,22 +799,18 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
static void write_actions(WriteData *wd, ListBase *idbase)
{
- bAction *act;
- bActionGroup *grp;
- TimeMarker *marker;
-
- for (act = idbase->first; act; act = act->id.next) {
+ for (bAction *act = idbase->first; act; act = act->id.next) {
if (act->id.us > 0 || wd->current) {
writestruct(wd, ID_AC, bAction, 1, act);
write_iddata(wd, &act->id);
write_fcurves(wd, &act->curves);
- for (grp = act->groups.first; grp; grp = grp->next) {
+ for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) {
writestruct(wd, DATA, bActionGroup, 1, grp);
}
- for (marker = act->markers.first; marker; marker = marker->next) {
+ for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
writestruct(wd, DATA, TimeMarker, 1, marker);
}
}
@@ -1280,13 +1276,7 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
}
static void write_particlesettings(WriteData *wd, ListBase *idbase)
{
- ParticleSettings *part;
- ParticleDupliWeight *dw;
- GroupObject *go;
- int a;
-
- part = idbase->first;
- while (part) {
+ for (ParticleSettings *part = idbase->first; part; part = part->id.next) {
if (part->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_PA, ParticleSettings, 1, part);
@@ -1306,24 +1296,23 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
write_curvemapping(wd, part->roughcurve);
}
- dw = part->dupliweights.first;
- for (; dw; dw = dw->next) {
+ for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) {
/* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
if (dw->ob != NULL) {
dw->index = 0;
if (part->dup_group) { /* can be NULL if lining fails or set to None */
- for (go = part->dup_group->gobject.first; go && go->ob != dw->ob; go = go->next, dw->index++);
+ for (GroupObject *go = part->dup_group->gobject.first;
+ go && go->ob != dw->ob;
+ go = go->next, dw->index++);
}
}
writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
}
if (part->boids && part->phystype == PART_PHYS_BOIDS) {
- BoidState *state = part->boids->states.first;
-
writestruct(wd, DATA, BoidSettings, 1, part->boids);
- for (; state; state = state->next) {
+ for (BoidState *state = part->boids->states.first; state; state = state->next) {
write_boid_state(wd, state);
}
}
@@ -1331,13 +1320,12 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid);
}
- for (a = 0; a < MAX_MTEX; a++) {
+ for (int a = 0; a < MAX_MTEX; a++) {
if (part->mtex[a]) {
writestruct(wd, DATA, MTex, 1, part->mtex[a]);
}
}
}
- part = part->id.next;
}
}
static void write_particlesystems(WriteData *wd, ListBase *particles)
@@ -1835,10 +1823,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
static void write_objects(WriteData *wd, ListBase *idbase)
{
- Object *ob;
-
- ob = idbase->first;
- while (ob) {
+ for (Object *ob = idbase->first; ob; ob = ob->id.next) {
if (ob->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_OB, Object, 1, ob);
@@ -1894,11 +1879,9 @@ static void write_objects(WriteData *wd, ListBase *idbase)
writelist(wd, DATA, LinkData, &ob->pc_ids);
writelist(wd, DATA, LodLevel, &ob->lodlevels);
- }
- write_previews(wd, ob->preview);
-
- ob = ob->id.next;
+ write_previews(wd, ob->preview);
+ }
}
mywrite_flush(wd);
@@ -1907,26 +1890,19 @@ static void write_objects(WriteData *wd, ListBase *idbase)
static void write_vfonts(WriteData *wd, ListBase *idbase)
{
- VFont *vf;
- PackedFile *pf;
-
- vf = idbase->first;
- while (vf) {
+ for (VFont *vf = idbase->first; vf; vf = vf->id.next) {
if (vf->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_VF, VFont, 1, vf);
write_iddata(wd, &vf->id);
/* direct data */
-
if (vf->packedfile) {
- pf = vf->packedfile;
+ PackedFile *pf = vf->packedfile;
writestruct(wd, DATA, PackedFile, 1, pf);
writedata(wd, DATA, pf->size, pf->data);
}
}
-
- vf = vf->id.next;
}
mywrite_flush(wd);
@@ -1935,11 +1911,7 @@ static void write_vfonts(WriteData *wd, ListBase *idbase)
static void write_keys(WriteData *wd, ListBase *idbase)
{
- Key *key;
- KeyBlock *kb;
-
- key = idbase->first;
- while (key) {
+ for (Key *key = idbase->first; key; key = key->id.next) {
if (key->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_KE, Key, 1, key);
@@ -1950,17 +1922,13 @@ static void write_keys(WriteData *wd, ListBase *idbase)
}
/* direct data */
- kb = key->block.first;
- while (kb) {
+ for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
writestruct(wd, DATA, KeyBlock, 1, kb);
if (kb->data) {
writedata(wd, DATA, kb->totelem * key->elemsize, kb->data);
}
- kb = kb->next;
}
}
-
- key = key->id.next;
}
mywrite_flush(wd);
@@ -1968,10 +1936,7 @@ static void write_keys(WriteData *wd, ListBase *idbase)
static void write_cameras(WriteData *wd, ListBase *idbase)
{
- Camera *cam;
-
- cam = idbase->first;
- while (cam) {
+ for (Camera *cam = idbase->first; cam; cam = cam->id.next) {
if (cam->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_CA, Camera, 1, cam);
@@ -1981,18 +1946,12 @@ static void write_cameras(WriteData *wd, ListBase *idbase)
write_animdata(wd, cam->adt);
}
}
-
- cam = cam->id.next;
}
}
static void write_mballs(WriteData *wd, ListBase *idbase)
{
- MetaBall *mb;
- MetaElem *ml;
-
- mb = idbase->first;
- while (mb) {
+ for (MetaBall *mb = idbase->first; mb; mb = mb->id.next) {
if (mb->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_MB, MetaBall, 1, mb);
@@ -2004,23 +1963,16 @@ static void write_mballs(WriteData *wd, ListBase *idbase)
write_animdata(wd, mb->adt);
}
- ml = mb->elems.first;
- while (ml) {
+ for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) {
writestruct(wd, DATA, MetaElem, 1, ml);
- ml = ml->next;
}
}
- mb = mb->id.next;
}
}
static void write_curves(WriteData *wd, ListBase *idbase)
{
- Curve *cu;
- Nurb *nu;
-
- cu = idbase->first;
- while (cu) {
+ for (Curve *cu = idbase->first; cu; cu = cu->id.next) {
if (cu->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_CU, Curve, 1, cu);
@@ -2039,13 +1991,10 @@ static void write_curves(WriteData *wd, ListBase *idbase)
}
else {
/* is also the order of reading */
- nu = cu->nurb.first;
- while (nu) {
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
writestruct(wd, DATA, Nurb, 1, nu);
- nu = nu->next;
}
- nu = cu->nurb.first;
- while (nu) {
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt);
}
@@ -2058,11 +2007,9 @@ static void write_curves(WriteData *wd, ListBase *idbase)
writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv);
}
}
- nu = nu->next;
}
}
}
- cu = cu->id.next;
}
mywrite_flush(wd);
@@ -2184,15 +2131,13 @@ static void write_customdata(
static void write_meshes(WriteData *wd, ListBase *idbase)
{
- Mesh *mesh;
- bool save_for_old_blender = false;
-
#ifdef USE_BMESH_SAVE_AS_COMPAT
- save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */
+ const bool save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */
+#else
+ const bool save_for_old_blender = false;
#endif
- mesh = idbase->first;
- while (mesh) {
+ for (Mesh *mesh = idbase->first; mesh; mesh = mesh->id.next) {
CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
@@ -2336,8 +2281,6 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
if (players && players != players_buff) {
MEM_freeN(players);
}
-
- mesh = mesh->id.next;
}
mywrite_flush(wd);
@@ -2345,10 +2288,7 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
static void write_lattices(WriteData *wd, ListBase *idbase)
{
- Lattice *lt;
-
- lt = idbase->first;
- while (lt) {
+ for (Lattice *lt = idbase->first; lt; lt = lt->id.next) {
if (lt->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_LT, Lattice, 1, lt);
@@ -2363,9 +2303,7 @@ static void write_lattices(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
-
}
- lt = lt->id.next;
}
mywrite_flush(wd);
@@ -2373,14 +2311,10 @@ static void write_lattices(WriteData *wd, ListBase *idbase)
static void write_images(WriteData *wd, ListBase *idbase)
{
- Image *ima;
- PackedFile *pf;
- ImageView *iv;
- ImagePackedFile *imapf;
-
- ima = idbase->first;
- while (ima) {
+ for (Image *ima = idbase->first; ima; ima = ima->id.next) {
if (ima->id.us > 0 || wd->current) {
+ ImagePackedFile *imapf;
+
/* Some trickery to keep forward compatibility of packed images. */
BLI_assert(ima->packedfile == NULL);
if (ima->packedfiles.first != NULL) {
@@ -2395,7 +2329,7 @@ static void write_images(WriteData *wd, ListBase *idbase)
for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
writestruct(wd, DATA, ImagePackedFile, 1, imapf);
if (imapf->packedfile) {
- pf = imapf->packedfile;
+ PackedFile *pf = imapf->packedfile;
writestruct(wd, DATA, PackedFile, 1, pf);
writedata(wd, DATA, pf->size, pf->data);
}
@@ -2403,14 +2337,13 @@ static void write_images(WriteData *wd, ListBase *idbase)
write_previews(wd, ima->preview);
- for (iv = ima->views.first; iv; iv = iv->next) {
+ for (ImageView *iv = ima->views.first; iv; iv = iv->next) {
writestruct(wd, DATA, ImageView, 1, iv);
}
writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format);
ima->packedfile = NULL;
}
- ima = ima->id.next;
}
mywrite_flush(wd);
@@ -2418,10 +2351,7 @@ static void write_images(WriteData *wd, ListBase *idbase)
static void write_textures(WriteData *wd, ListBase *idbase)
{
- Tex *tex;
-
- tex = idbase->first;
- while (tex) {
+ for (Tex *tex = idbase->first; tex; tex = tex->id.next) {
if (tex->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_TE, Tex, 1, tex);
@@ -2462,7 +2392,6 @@ static void write_textures(WriteData *wd, ListBase *idbase)
write_previews(wd, tex->preview);
}
- tex = tex->id.next;
}
mywrite_flush(wd);
@@ -2470,11 +2399,7 @@ static void write_textures(WriteData *wd, ListBase *idbase)
static void write_materials(WriteData *wd, ListBase *idbase)
{
- Material *ma;
- int a;
-
- ma = idbase->first;
- while (ma) {
+ for (Material *ma = idbase->first; ma; ma = ma->id.next) {
if (ma->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_MA, Material, 1, ma);
@@ -2484,7 +2409,7 @@ static void write_materials(WriteData *wd, ListBase *idbase)
write_animdata(wd, ma->adt);
}
- for (a = 0; a < MAX_MTEX; a++) {
+ for (int a = 0; a < MAX_MTEX; a++) {
if (ma->mtex[a]) {
writestruct(wd, DATA, MTex, 1, ma->mtex[a]);
}
@@ -2505,17 +2430,12 @@ static void write_materials(WriteData *wd, ListBase *idbase)
write_previews(wd, ma->preview);
}
- ma = ma->id.next;
}
}
static void write_worlds(WriteData *wd, ListBase *idbase)
{
- World *wrld;
- int a;
-
- wrld = idbase->first;
- while (wrld) {
+ for (World *wrld = idbase->first; wrld; wrld = wrld->id.next) {
if (wrld->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_WO, World, 1, wrld);
@@ -2525,7 +2445,7 @@ static void write_worlds(WriteData *wd, ListBase *idbase)
write_animdata(wd, wrld->adt);
}
- for (a = 0; a < MAX_MTEX; a++) {
+ for (int a = 0; a < MAX_MTEX; a++) {
if (wrld->mtex[a]) {
writestruct(wd, DATA, MTex, 1, wrld->mtex[a]);
}
@@ -2539,17 +2459,12 @@ static void write_worlds(WriteData *wd, ListBase *idbase)
write_previews(wd, wrld->preview);
}
- wrld = wrld->id.next;
}
}
static void write_lamps(WriteData *wd, ListBase *idbase)
{
- Lamp *la;
- int a;
-
- la = idbase->first;
- while (la) {
+ for (Lamp *la = idbase->first; la; la = la->id.next) {
if (la->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_LA, Lamp, 1, la);
@@ -2560,7 +2475,7 @@ static void write_lamps(WriteData *wd, ListBase *idbase)
}
/* direct data */
- for (a = 0; a < MAX_MTEX; a++) {
+ for (int a = 0; a < MAX_MTEX; a++) {
if (la->mtex[a]) {
writestruct(wd, DATA, MTex, 1, la->mtex[a]);
}
@@ -2577,9 +2492,7 @@ static void write_lamps(WriteData *wd, ListBase *idbase)
}
write_previews(wd, la->preview);
-
}
- la = la->id.next;
}
mywrite_flush(wd);
@@ -2628,22 +2541,7 @@ static void write_paint(WriteData *wd, Paint *p)
static void write_scenes(WriteData *wd, ListBase *scebase)
{
- Scene *sce;
- Base *base;
- Editing *ed;
- Sequence *seq;
- MetaStack *ms;
- Strip *strip;
- TimeMarker *marker;
- TransformOrientation *ts;
- SceneRenderLayer *srl;
- SceneRenderView *srv;
- ToolSettings *tos;
- FreestyleModuleConfig *fmc;
- FreestyleLineSet *fls;
-
- sce = scebase->first;
- while (sce) {
+ for (Scene *sce = scebase->first; sce; sce = sce->id.next) {
/* write LibData */
writestruct(wd, ID_SCE, Scene, 1, sce);
write_iddata(wd, &sce->id);
@@ -2654,13 +2552,11 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
write_keyingsets(wd, &sce->keyingsets);
/* direct data */
- base = sce->base.first;
- while (base) {
+ for (Base *base = sce->base.first; base; base = base->next) {
writestruct(wd, DATA, Base, 1, base);
- base = base->next;
}
- tos = sce->toolsettings;
+ ToolSettings *tos = sce->toolsettings;
writestruct(wd, DATA, ToolSettings, 1, tos);
if (tos->vpaint) {
writestruct(wd, DATA, VPaint, 1, tos->vpaint);
@@ -2699,8 +2595,10 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
write_paint(wd, &tos->imapaint.paint);
- ed = sce->ed;
+ Editing *ed = sce->ed;
if (ed) {
+ Sequence *seq;
+
writestruct(wd, DATA, Editing, 1, ed);
/* reset write flags too */
@@ -2747,7 +2645,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format);
- strip = seq->strip;
+ Strip *strip = seq->strip;
writestruct(wd, DATA, Strip, 1, strip);
if (seq->flag & SEQ_USE_CROP && strip->crop) {
writestruct(wd, DATA, StripCrop, 1, strip->crop);
@@ -2779,7 +2677,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
SEQ_END
/* new; meta stack too, even when its nasty restore code */
- for (ms = ed->metastack.first; ms; ms = ms->next) {
+ for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) {
writestruct(wd, DATA, MetaStack, 1, ms);
}
}
@@ -2805,27 +2703,27 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
}
/* writing dynamic list of TimeMarkers to the blend file */
- for (marker = sce->markers.first; marker; marker = marker->next) {
+ for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) {
writestruct(wd, DATA, TimeMarker, 1, marker);
}
/* writing dynamic list of TransformOrientations to the blend file */
- for (ts = sce->transform_spaces.first; ts; ts = ts->next) {
+ for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) {
writestruct(wd, DATA, TransformOrientation, 1, ts);
}
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
writestruct(wd, DATA, SceneRenderLayer, 1, srl);
- for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
+ for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
}
- for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
+ for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
writestruct(wd, DATA, FreestyleLineSet, 1, fls);
}
}
/* writing MultiView to the blend file */
- for (srv = sce->r.views.first; srv; srv = srv->next) {
+ for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) {
writestruct(wd, DATA, SceneRenderView, 1, srv);
}
@@ -2845,8 +2743,6 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
write_previews(wd, sce->preview);
write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
-
- sce = sce->id.next;
}
mywrite_flush(wd);
@@ -2854,13 +2750,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
static void write_gpencils(WriteData *wd, ListBase *lb)
{
- bGPdata *gpd;
- bGPDlayer *gpl;
- bGPDframe *gpf;
- bGPDstroke *gps;
- bGPDpalette *palette;
-
- for (gpd = lb->first; gpd; gpd = gpd->id.next) {
+ for (bGPdata *gpd = lb->first; gpd; gpd = gpd->id.next) {
if (gpd->id.us > 0 || wd->current) {
/* write gpd data block to file */
writestruct(wd, ID_GD, bGPdata, 1, gpd);
@@ -2872,22 +2762,21 @@ static void write_gpencils(WriteData *wd, ListBase *lb)
/* write grease-pencil layers to file */
writelist(wd, DATA, bGPDlayer, &gpd->layers);
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
-
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
/* write this layer's frames to file */
writelist(wd, DATA, bGPDframe, &gpl->frames);
- for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
-
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
/* write strokes */
writelist(wd, DATA, bGPDstroke, &gpf->strokes);
- for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points);
}
}
}
+
/* write grease-pencil palettes */
writelist(wd, DATA, bGPDpalette, &gpd->palettes);
- for (palette = gpd->palettes.first; palette; palette = palette->next) {
+ for (bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
writelist(wd, DATA, bGPDpalettecolor, &palette->colors);
}
}
@@ -2898,14 +2787,11 @@ static void write_gpencils(WriteData *wd, ListBase *lb)
static void write_windowmanagers(WriteData *wd, ListBase *lb)
{
- wmWindowManager *wm;
- wmWindow *win;
-
- for (wm = lb->first; wm; wm = wm->id.next) {
+ for (wmWindowManager *wm = lb->first; wm; wm = wm->id.next) {
writestruct(wd, ID_WM, wmWindowManager, 1, wm);
write_iddata(wd, &wm->id);
- for (win = wm->windows.first; win; win = win->next) {
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
writestruct(wd, DATA, wmWindow, 1, win);
writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
}
@@ -2998,29 +2884,22 @@ static void write_soops(WriteData *wd, SpaceOops *so)
static void write_screens(WriteData *wd, ListBase *scrbase)
{
- bScreen *sc;
- ScrArea *sa;
- ScrVert *sv;
- ScrEdge *se;
-
- sc = scrbase->first;
- while (sc) {
-
+ for (bScreen *sc = scrbase->first; sc; sc = sc->id.next) {
/* write LibData */
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
writestruct(wd, ID_SCRN, bScreen, 1, sc);
write_iddata(wd, &sc->id);
/* direct data */
- for (sv = sc->vertbase.first; sv; sv = sv->next) {
+ for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) {
writestruct(wd, DATA, ScrVert, 1, sv);
}
- for (se = sc->edgebase.first; se; se = se->next) {
+ for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
writestruct(wd, DATA, ScrEdge, 1, se);
}
- for (sa = sc->areabase.first; sa; sa = sa->next) {
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
SpaceLink *sl;
Panel *pa;
uiList *ui_list;
@@ -3050,8 +2929,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
}
}
- sl = sa->spacedata.first;
- while (sl) {
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
for (ar = sl->regionbase.first; ar; ar = ar->next) {
write_region(wd, ar, sl->spacetype);
}
@@ -3165,12 +3043,8 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
else if (sl->spacetype == SPACE_INFO) {
writestruct(wd, DATA, SpaceInfo, 1, sl);
}
-
- sl = sl->next;
}
}
-
- sc = sc->id.next;
}
mywrite_flush(wd);
@@ -3198,11 +3072,7 @@ static void write_bone(WriteData *wd, Bone *bone)
static void write_armatures(WriteData *wd, ListBase *idbase)
{
- bArmature *arm;
- Bone *bone;
-
- arm = idbase->first;
- while (arm) {
+ for (bArmature *arm = idbase->first; arm; arm = arm->id.next) {
if (arm->id.us > 0 || wd->current) {
writestruct(wd, ID_AR, bArmature, 1, arm);
write_iddata(wd, &arm->id);
@@ -3212,13 +3082,10 @@ static void write_armatures(WriteData *wd, ListBase *idbase)
}
/* Direct data */
- bone = arm->bonebase.first;
- while (bone) {
+ for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
write_bone(wd, bone);
- bone = bone->next;
}
}
- arm = arm->id.next;
}
mywrite_flush(wd);
@@ -3226,12 +3093,8 @@ static void write_armatures(WriteData *wd, ListBase *idbase)
static void write_texts(WriteData *wd, ListBase *idbase)
{
- Text *text;
- TextLine *tmp;
-
- text = idbase->first;
- while (text) {
- if ( (text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
+ for (Text *text = idbase->first; text; text = text->id.next) {
+ if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
text->flags &= ~TXT_ISEXT;
}
@@ -3245,21 +3108,14 @@ static void write_texts(WriteData *wd, ListBase *idbase)
if (!(text->flags & TXT_ISEXT)) {
/* now write the text data, in two steps for optimization in the readfunction */
- tmp = text->lines.first;
- while (tmp) {
+ for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
writestruct(wd, DATA, TextLine, 1, tmp);
- tmp = tmp->next;
}
- tmp = text->lines.first;
- while (tmp) {
+ for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
writedata(wd, DATA, tmp->len + 1, tmp->line);
- tmp = tmp->next;
}
}
-
-
- text = text->id.next;
}
mywrite_flush(wd);
@@ -3267,10 +3123,7 @@ static void write_texts(WriteData *wd, ListBase *idbase)
static void write_speakers(WriteData *wd, ListBase *idbase)
{
- Speaker *spk;
-
- spk = idbase->first;
- while (spk) {
+ for (Speaker *spk = idbase->first; spk; spk = spk->id.next) {
if (spk->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_SPK, Speaker, 1, spk);
@@ -3280,30 +3133,23 @@ static void write_speakers(WriteData *wd, ListBase *idbase)
write_animdata(wd, spk->adt);
}
}
- spk = spk->id.next;
}
}
static void write_sounds(WriteData *wd, ListBase *idbase)
{
- bSound *sound;
-
- PackedFile *pf;
-
- sound = idbase->first;
- while (sound) {
+ for (bSound *sound = idbase->first; sound; sound = sound->id.next) {
if (sound->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_SO, bSound, 1, sound);
write_iddata(wd, &sound->id);
if (sound->packedfile) {
- pf = sound->packedfile;
+ PackedFile *pf = sound->packedfile;
writestruct(wd, DATA, PackedFile, 1, pf);
writedata(wd, DATA, pf->size, pf->data);
}
}
- sound = sound->id.next;
}
mywrite_flush(wd);
@@ -3311,10 +3157,7 @@ static void write_sounds(WriteData *wd, ListBase *idbase)
static void write_groups(WriteData *wd, ListBase *idbase)
{
- Group *group;
- GroupObject *go;
-
- for (group = idbase->first; group; group = group->id.next) {
+ for (Group *group = idbase->first; group; group = group->id.next) {
if (group->id.us > 0 || wd->current) {
/* write LibData */
writestruct(wd, ID_GR, Group, 1, group);
@@ -3322,10 +3165,8 @@ static void write_groups(WriteData *wd, ListBase *idbase)
write_previews(wd, group->preview);
- go = group->gobject.first;
- while (go) {
+ for (GroupObject *go = group->gobject.first; go; go = go->next) {
writestruct(wd, DATA, GroupObject, 1, go);
- go = go->next;
}
}
}
@@ -3335,9 +3176,7 @@ static void write_groups(WriteData *wd, ListBase *idbase)
static void write_nodetrees(WriteData *wd, ListBase *idbase)
{
- bNodeTree *ntree;
-
- for (ntree = idbase->first; ntree; ntree = ntree->id.next) {
+ for (bNodeTree *ntree = idbase->first; ntree; ntree = ntree->id.next) {
if (ntree->id.us > 0 || wd->current) {
writestruct(wd, ID_NT, bNodeTree, 1, ntree);
/* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot
@@ -3421,9 +3260,7 @@ static void customnodes_free_deprecated_data(Main *mainvar)
static void write_brushes(WriteData *wd, ListBase *idbase)
{
- Brush *brush;
-
- for (brush = idbase->first; brush; brush = brush->id.next) {
+ for (Brush *brush = idbase->first; brush; brush = brush->id.next) {
if (brush->id.us > 0 || wd->current) {
writestruct(wd, ID_BR, Brush, 1, brush);
write_iddata(wd, &brush->id);
@@ -3440,9 +3277,7 @@ static void write_brushes(WriteData *wd, ListBase *idbase)
static void write_palettes(WriteData *wd, ListBase *idbase)
{
- Palette *palette;
-
- for (palette = idbase->first; palette; palette = palette->id.next) {
+ for (Palette *palette = idbase->first; palette; palette = palette->id.next) {
if (palette->id.us > 0 || wd->current) {
PaletteColor *color;
writestruct(wd, ID_PAL, Palette, 1, palette);
@@ -3457,9 +3292,7 @@ static void write_palettes(WriteData *wd, ListBase *idbase)
static void write_paintcurves(WriteData *wd, ListBase *idbase)
{
- PaintCurve *pc;
-
- for (pc = idbase->first; pc; pc = pc->id.next) {
+ for (PaintCurve *pc = idbase->first; pc; pc = pc->id.next) {
if (pc->id.us > 0 || wd->current) {
writestruct(wd, ID_PC, PaintCurve, 1, pc);
write_iddata(wd, &pc->id);
@@ -3509,10 +3342,7 @@ static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction
static void write_movieclips(WriteData *wd, ListBase *idbase)
{
- MovieClip *clip;
-
- clip = idbase->first;
- while (clip) {
+ for (MovieClip *clip = idbase->first; clip; clip = clip->id.next) {
if (clip->id.us > 0 || wd->current) {
MovieTracking *tracking = &clip->tracking;
MovieTrackingObject *object;
@@ -3539,8 +3369,6 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
object = object->next;
}
}
-
- clip = clip->id.next;
}
mywrite_flush(wd);
@@ -3548,10 +3376,7 @@ static void write_movieclips(WriteData *wd, ListBase *idbase)
static void write_masks(WriteData *wd, ListBase *idbase)
{
- Mask *mask;
-
- mask = idbase->first;
- while (mask) {
+ for (Mask *mask = idbase->first; mask; mask = mask->id.next) {
if (mask->id.us > 0 || wd->current) {
MaskLayer *masklay;
@@ -3599,8 +3424,6 @@ static void write_masks(WriteData *wd, ListBase *idbase)
}
}
}
-
- mask = mask->id.next;
}
mywrite_flush(wd);
@@ -3862,10 +3685,7 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier
static void write_linestyles(WriteData *wd, ListBase *idbase)
{
- FreestyleLineStyle *linestyle;
- int a;
-
- for (linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) {
+ for (FreestyleLineStyle *linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) {
if (linestyle->id.us > 0 || wd->current) {
writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle);
write_iddata(wd, &linestyle->id);
@@ -3878,7 +3698,7 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
- for (a = 0; a < MAX_MTEX; a++) {
+ for (int a = 0; a < MAX_MTEX; a++) {
if (linestyle->mtex[a]) {
writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]);
}
@@ -3893,9 +3713,7 @@ static void write_linestyles(WriteData *wd, ListBase *idbase)
static void write_cachefiles(WriteData *wd, ListBase *idbase)
{
- CacheFile *cache_file;
-
- for (cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) {
+ for (CacheFile *cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) {
if (cache_file->id.us > 0 || wd->current) {
writestruct(wd, ID_CF, CacheFile, 1, cache_file);
@@ -3915,7 +3733,6 @@ static void write_libraries(WriteData *wd, Main *main)
bool found_one;
for (; main; main = main->next) {
-
a = tot = set_listbasepointers(main, lbarray);
/* test: is lib being used */
@@ -3924,16 +3741,13 @@ static void write_libraries(WriteData *wd, Main *main)
}
else {
found_one = false;
- while (tot--) {
+ while (!found_one && tot--) {
for (id = lbarray[tot]->first; id; id = id->next) {
if (id->us > 0 && (id->tag & LIB_TAG_EXTERN)) {
found_one = true;
break;
}
}
- if (found_one) {
- break;
- }
}
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index 065f65659e6..3a042535d26 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -53,6 +53,7 @@ extern "C" {
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
#include "intern/depsgraph.h"
+#include "intern/depsgraph_intern.h"
#include "util/deg_util_foreach.h"
/* Unfinished and unused, and takes quite some pre-processing time. */
@@ -362,6 +363,11 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
return;
}
+ DEG_DEBUG_PRINTF("%s: layers:%u, graph->layers:%u\n",
+ __func__,
+ layers,
+ graph->layers);
+
/* Set time for the current graph evaluation context. */
TimeSourceDepsNode *time_src = graph->find_time_source();
eval_ctx->ctime = time_src->cfra;
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 33e44d73894..98900812bb2 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -46,6 +46,8 @@
#include "BLI_dlrbTree.h"
#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_nla.h"
#include "BKE_mask.h"
@@ -115,7 +117,8 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
/* Draw a light green line to indicate current frame */
UI_ThemeColor(TH_CFRAME);
- const float x = (float)(scene->r.cfra * scene->r.framelen);
+ const float time = scene->r.cfra + scene->r.subframe;
+ const float x = (float)(time * scene->r.framelen);
glLineWidth((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);
@@ -308,7 +311,8 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo
fcu->prev_norm_factor = 1.0f;
if (fcu->bezt) {
- BezTriple *bezt;
+ const bool use_preview_only = PRVRANGEON;
+ const BezTriple *bezt;
int i;
float max_coord = -FLT_MAX;
float min_coord = FLT_MAX;
@@ -318,28 +322,77 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo
return 1.0f;
}
- if (PRVRANGEON) {
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) {
- max_coord = max_ff(max_coord, bezt->vec[0][1]);
- max_coord = max_ff(max_coord, bezt->vec[1][1]);
- max_coord = max_ff(max_coord, bezt->vec[2][1]);
-
- min_coord = min_ff(min_coord, bezt->vec[0][1]);
- min_coord = min_ff(min_coord, bezt->vec[1][1]);
- min_coord = min_ff(min_coord, bezt->vec[2][1]);
- }
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (use_preview_only && !IN_RANGE_INCL(bezt->vec[1][0],
+ scene->r.psfra,
+ scene->r.pefra))
+ {
+ continue;
}
- }
- else {
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- max_coord = max_ff(max_coord, bezt->vec[0][1]);
+
+ if (i == 0) {
+ /* We ignore extrapolation flags and handle here, and use the
+ * control point position only. so we normalize "interesting"
+ * part of the curve.
+ *
+ * Here we handle left extrapolation.
+ */
max_coord = max_ff(max_coord, bezt->vec[1][1]);
- max_coord = max_ff(max_coord, bezt->vec[2][1]);
- min_coord = min_ff(min_coord, bezt->vec[0][1]);
min_coord = min_ff(min_coord, bezt->vec[1][1]);
- min_coord = min_ff(min_coord, bezt->vec[2][1]);
+ }
+ else {
+ const BezTriple *prev_bezt = bezt - 1;
+ if (prev_bezt->ipo == BEZT_IPO_CONST) {
+ /* Constant interpolation: previous CV value is used up
+ * to the current keyframe.
+ */
+ max_coord = max_ff(max_coord, bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, bezt->vec[1][1]);
+ }
+ else if (prev_bezt->ipo == BEZT_IPO_LIN) {
+ /* Linear interpolation: min/max using both previous and
+ * and current CV.
+ */
+ max_coord = max_ff(max_coord, bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, bezt->vec[1][1]);
+ max_coord = max_ff(max_coord, prev_bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
+ }
+ else if (prev_bezt->ipo == BEZT_IPO_BEZ) {
+ const int resol = fcu->driver
+ ? 32
+ : min_ii((int)(5.0f * len_v2v2(bezt->vec[1], prev_bezt->vec[1])), 32);
+ if (resol < 2) {
+ max_coord = max_ff(max_coord, prev_bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
+ }
+ else {
+ float data[120];
+ float v1[2], v2[2], v3[2], v4[2];
+
+ v1[0] = prev_bezt->vec[1][0];
+ v1[1] = prev_bezt->vec[1][1];
+ v2[0] = prev_bezt->vec[2][0];
+ v2[1] = prev_bezt->vec[2][1];
+
+ v3[0] = bezt->vec[0][0];
+ v3[1] = bezt->vec[0][1];
+ v4[0] = bezt->vec[1][0];
+ v4[1] = bezt->vec[1][1];
+
+ correct_bezpart(v1, v2, v3, v4);
+
+ BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3);
+ BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3);
+
+ for (int j = 0; j <= resol; ++j) {
+ const float *fp = &data[j * 3];
+ max_coord = max_ff(max_coord, fp[1]);
+ min_coord = min_ff(min_coord, fp[1]);
+ }
+ }
+ }
}
}
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index c0d6963acbb..bb73cbf03b4 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -95,7 +95,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- int frame = RNA_int_get(op->ptr, "frame");
+ float frame = RNA_float_get(op->ptr, "frame");
bool do_snap = RNA_boolean_get(op->ptr, "snap");
if (do_snap && CTX_wm_space_seq(C)) {
@@ -103,10 +103,15 @@ static void change_frame_apply(bContext *C, wmOperator *op)
}
/* set the new frame number */
- CFRA = frame;
+ CFRA = (int)frame;
+ if (scene->r.flag & SCER_SHOW_SUBFRAME) {
+ SUBFRA = frame - (int)frame;
+ }
+ else {
+ SUBFRA = 0.0f;
+ }
FRAMENUMBER_MIN_CLAMP(CFRA);
- SUBFRA = 0.0f;
-
+
/* do updates */
BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
@@ -125,18 +130,18 @@ static int change_frame_exec(bContext *C, wmOperator *op)
/* ---- */
/* Get frame from mouse coordinates */
-static int frame_from_event(bContext *C, const wmEvent *event)
+static float frame_from_event(bContext *C, const wmEvent *event)
{
ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
float viewx;
- int frame;
+ float frame;
/* convert from region coordinates to View2D 'tot' space */
viewx = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
/* round result to nearest int (frames are ints!) */
- frame = iroundf(viewx);
+ frame = viewx;
if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
CLAMP(frame, PSFRA, PEFRA);
@@ -187,7 +192,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
* as user could click on a single frame (jump to frame) as well as
* click-dragging over a range (modal scrubbing).
*/
- RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+ RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
change_frame_seq_preview_begin(C, event);
@@ -215,7 +220,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
case MOUSEMOVE:
- RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+ RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
change_frame_apply(C, op);
break;
@@ -268,7 +273,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
ot->undo_group = "FRAME_CHANGE";
/* rna */
- ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+ ot->prop = RNA_def_float(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index cc4c1809fbc..f6c04e9570a 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -970,6 +970,9 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
ToolSettings *ts = CTX_data_tool_settings(C);
int point_added = 0;
+ /* TODO: Since the function `ED_transform_snap_object_context_create_view3d` creates a cache,
+ * the ideal would be to call this function only at the beginning of the snap operation,
+ * or at the beginning of the operator itself */
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
CTX_data_main(C), CTX_data_scene(C), 0,
CTX_wm_region(C), CTX_wm_view3d(C));
@@ -1038,6 +1041,8 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
}
}
+ /* TODO: The ideal would be to call this function only once.
+ * At the end of the operator */
ED_transform_snap_object_context_destroy(snap_context);
return point_added;
}
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 5b011b679a6..e118e490f25 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -953,6 +953,9 @@ static int gp_dissolve_selected_points(bContext *C)
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false)
continue;
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(gpl, gps) == false)
+ continue;
if (gps->flag & GP_STROKE_SELECT) {
bGPDspoint *pt;
@@ -1165,6 +1168,9 @@ static int gp_delete_selected_points(bContext *C)
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false)
continue;
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(gpl, gps) == false)
+ continue;
if (gps->flag & GP_STROKE_SELECT) {
@@ -1204,7 +1210,7 @@ static int gp_delete_exec(bContext *C, wmOperator *op)
case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */
result = gp_delete_selected_points(C);
break;
-
+
case GP_DELETEOP_FRAME: /* active frame */
result = gp_actframe_delete_exec(C, op);
break;
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index 7944b434057..6eaae49912c 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -65,10 +65,6 @@ struct SnapObjectParams {
unsigned int use_object_edit_cage : 1;
};
-enum {
- SNAP_OBJECT_USE_CACHE = (1 << 0),
-};
-
typedef struct SnapObjectContext SnapObjectContext;
SnapObjectContext *ED_transform_snap_object_context_create(
struct Main *bmain, struct Scene *scene, int flag);
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 8579778ff79..8420591aa3e 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -653,9 +653,9 @@ DEF_ICON(IPO_BACK)
DEF_ICON(IPO_EASE_IN)
DEF_ICON(IPO_EASE_OUT)
DEF_ICON(IPO_EASE_IN_OUT)
+DEF_ICON(NORMALIZE_FCURVES)
#ifndef DEF_ICON_BLANK_SKIP
/* available */
- DEF_ICON(BLANK203)
DEF_ICON(BLANK204)
DEF_ICON(BLANK205)
DEF_ICON(BLANK206)
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index d43a94c5514..b3736a71e74 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1584,7 +1584,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
- widget_draw_icon(but, ICON_X, alpha, &temp, false);
+ widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp, false);
}
else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false);
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 8f004bcf72b..65ee097e8e1 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -306,7 +306,7 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
ED_view3d_init_mats_rv3d(obedit, ar->regiondata);
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE,
+ CTX_data_main(C), CTX_data_scene(C), 0,
ar, CTX_wm_view3d(C));
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 56f59dca9a1..3c406764157 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -363,8 +363,8 @@ void ED_vgroup_parray_remove_zero(MDeformVert **dvert_array, const int dvert_tot
/* matching index only */
bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
{
- MDeformVert **dvert_array_from, **dvf;
- MDeformVert **dvert_array, **dv;
+ MDeformVert **dvert_array_from = NULL, **dvf;
+ MDeformVert **dvert_array = NULL, **dv;
int dvert_tot_from;
int dvert_tot;
int i;
@@ -375,26 +375,30 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
if (ob == ob_from)
return true;
- ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
- ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
-
- if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) {
+ /* in case we copy vgroup between two objects using same data, we only have to care about object side of things. */
+ if (ob->data != ob_from->data) {
+ ED_vgroup_parray_alloc(ob_from->data, &dvert_array_from, &dvert_tot_from, false);
ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
- new_vgroup = true;
- }
- if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) {
+ if ((dvert_array == NULL) && (dvert_array_from != NULL) && BKE_object_defgroup_data_create(ob->data)) {
+ ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false);
+ new_vgroup = true;
+ }
- if (dvert_array) MEM_freeN(dvert_array);
- if (dvert_array_from) MEM_freeN(dvert_array_from);
+ if (dvert_tot == 0 || (dvert_tot != dvert_tot_from) || dvert_array_from == NULL || dvert_array == NULL) {
+ if (dvert_array)
+ MEM_freeN(dvert_array);
+ if (dvert_array_from)
+ MEM_freeN(dvert_array_from);
- if (new_vgroup == true) {
- /* free the newly added vgroup since it wasn't compatible */
- BKE_object_defgroup_remove_all(ob);
- }
+ if (new_vgroup == true) {
+ /* free the newly added vgroup since it wasn't compatible */
+ BKE_object_defgroup_remove_all(ob);
+ }
- /* if true: both are 0 and nothing needs changing, consider this a success */
- return (dvert_tot == dvert_tot_from);
+ /* if true: both are 0 and nothing needs changing, consider this a success */
+ return (dvert_tot == dvert_tot_from);
+ }
}
/* do the copy */
@@ -412,22 +416,23 @@ bool ED_vgroup_array_copy(Object *ob, Object *ob_from)
MEM_freeN(remap);
}
- dvf = dvert_array_from;
- dv = dvert_array;
+ if (dvert_array_from != NULL && dvert_array != NULL) {
+ dvf = dvert_array_from;
+ dv = dvert_array;
- for (i = 0; i < dvert_tot; i++, dvf++, dv++) {
- if ((*dv)->dw)
- MEM_freeN((*dv)->dw);
+ for (i = 0; i < dvert_tot; i++, dvf++, dv++) {
+ MEM_SAFE_FREE((*dv)->dw);
+ *(*dv) = *(*dvf);
- *(*dv) = *(*dvf);
+ if ((*dv)->dw) {
+ (*dv)->dw = MEM_dupallocN((*dv)->dw);
+ }
+ }
- if ((*dv)->dw)
- (*dv)->dw = MEM_dupallocN((*dv)->dw);
+ MEM_freeN(dvert_array);
+ MEM_freeN(dvert_array_from);
}
- MEM_freeN(dvert_array);
- MEM_freeN(dvert_array_from);
-
return true;
}
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 9097432a251..55c07140216 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -887,13 +887,13 @@ static void write_result_func(TaskPool * __restrict pool,
ReportList reports;
BKE_reports_init(&reports, oglrender->reports->flag & ~RPT_PRINT);
/* Do actual save logic here, depending on the file format. */
+ Scene tmp_scene = *scene;
+ tmp_scene.r.cfra = cfra;
if (is_movie) {
/* We have to construct temporary scene with proper scene->r.cfra.
* This is because underlying calls do not use r.cfra but use scene
* for that.
*/
- Scene tmp_scene = *scene;
- tmp_scene.r.cfra = cfra;
ok = RE_WriteRenderViewsMovie(&reports,
rr,
&tmp_scene,
@@ -917,8 +917,8 @@ static void write_result_func(TaskPool * __restrict pool,
true,
NULL);
- BKE_render_result_stamp_info(scene, scene->camera, rr, false);
- ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name);
+ BKE_render_result_stamp_info(&tmp_scene, tmp_scene.camera, rr, false);
+ ok = RE_WriteRenderViewsImage(NULL, rr, &tmp_scene, true, name);
if (!ok) {
BKE_reportf(&reports,
RPT_ERROR,
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 075b1faf502..964f4bcdd9c 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1256,21 +1256,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot
}
break;
}
-
- /* removed since BKE_image_user_frame_calc is now called in view3d_draw_bgpic because screen_ops doesnt call the notifier. */
-#if 0
- if (wmn->category == NC_SCENE && wmn->data == ND_FRAME) {
- View3D *v3d = area->spacedata.first;
- BGpic *bgpic = v3d->bgpicbase.first;
-
- for (; bgpic; bgpic = bgpic->next) {
- if (bgpic->ima) {
- Scene *scene = wmn->reference;
- BKE_image_user_frame_calc(&bgpic->iuser, scene->r.cfra, 0);
- }
- }
- }
-#endif
}
const char *view3d_context_dir[] = {
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index 688f459108b..aefe30bbe32 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -280,7 +280,7 @@ static void ruler_state_set(bContext *C, RulerInfo *ruler_info, int state)
}
else if (state == RULER_STATE_DRAG) {
ruler_info->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), CTX_data_scene(C), SNAP_OBJECT_USE_CACHE,
+ CTX_data_main(C), CTX_data_scene(C), 0,
ruler_info->ar, CTX_wm_view3d(C));
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 17c08ed4205..542dc410bc3 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -588,7 +588,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->rv3d->rflag |= RV3D_NAVIGATING;
walk->snap_context = ED_transform_snap_object_context_create_view3d(
- CTX_data_main(C), walk->scene, SNAP_OBJECT_USE_CACHE,
+ CTX_data_main(C), walk->scene, 0,
walk->ar, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 31ffa019e4e..1916f9b4dab 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -3722,6 +3722,12 @@ static void initRotation(TransInfo *t)
copy_v3_v3(t->axis_orig, t->axis);
}
+/**
+ * Applies values of rotation to `td->loc` and `td->ext->quat`
+ * based on a rotation matrix (mat) and a pivot (center).
+ *
+ * Protected axis and other transform settings are taken into account.
+ */
static void ElementRotation_ex(TransInfo *t, TransData *td, float mat[3][3], const float *center)
{
float vec[3], totmat[3][3], smat[3][3];
@@ -4339,9 +4345,22 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
{
TransData *td = t->data;
float tvec[3];
- int i;
- for (i = 0; i < t->total; i++, td++) {
+ /* The ideal would be "apply_snap_align_rotation" only when a snap point is found
+ * so, maybe inside this function is not the best place to apply this rotation.
+ * but you need "handle snapping rotation before doing the translation" (really?) */
+ const bool apply_snap_align_rotation = usingSnappingNormal(t);// && (t->tsnap.status & POINT_INIT);
+ float pivot[3];
+ if (apply_snap_align_rotation) {
+ copy_v3_v3(pivot, t->tsnap.snapTarget);
+ /* The pivot has to be in local-space (see T49494) */
+ if (t->flag & (T_EDIT | T_POSE)) {
+ Object *ob = t->obedit ? t->obedit : t->poseobj;
+ mul_m4_v3(ob->imat, pivot);
+ }
+ }
+
+ for (int i = 0; i < t->total; i++, td++) {
if (td->flag & TD_NOACTION)
break;
@@ -4352,7 +4371,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
bool use_rotate_offset = false;
/* handle snapping rotation before doing the translation */
- if (usingSnappingNormal(t)) {
+ if (apply_snap_align_rotation) {
float mat[3][3];
if (validSnappingNormal(t)) {
@@ -4370,7 +4389,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
unit_m3(mat);
}
- ElementRotation_ex(t, td, mat, t->tsnap.snapTarget);
+ ElementRotation_ex(t, td, mat, pivot);
if (td->loc) {
use_rotate_offset = true;
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 7ea4448a44e..d60eb2f0778 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -84,8 +84,8 @@ typedef struct TransSnap {
bool peel;
bool snap_spatial_grid;
short status;
- float snapPoint[3]; /* snapping from this point */
- float snapTarget[3]; /* to this point */
+ float snapPoint[3]; /* snapping from this point (in global-space)*/
+ float snapTarget[3]; /* to this point (in global-space)*/
float snapNormal[3];
char snapNodeBorder;
ListBase points;
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index ce3d903b8f6..091a5773cf0 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2393,7 +2393,12 @@ static void createTransEditVerts(TransInfo *t)
editmesh_set_connectivity_distance(em->bm, mtx, dists);
}
- if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ /* Only in case of rotation and resize, we want the elements of the edited
+ * object to behave as groups whose pivot are the individual origins
+ *
+ * TODO: use island_info to detect the closest point when the "Snap Target"
+ * in Blender UI is "Closest" */
+ if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION)) {
island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map);
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 87ac54b2bd9..318d2718969 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -601,7 +601,7 @@ static void initSnappingMode(TransInfo *t)
if (t->spacetype == SPACE_VIEW3D) {
if (t->tsnap.object_context == NULL) {
t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
- G.main, t->scene, SNAP_OBJECT_USE_CACHE,
+ G.main, t->scene, 0,
t->ar, t->view);
ED_transform_snap_object_context_set_editmesh_callbacks(
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 85209b07677..53f6b37c22e 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -235,21 +235,6 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
/** \Common utilities
* \{ */
-MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3])
-{
- float dvec[3];
- sub_v3_v3v3(dvec, co, ray_start);
- return dot_v3v3(dvec, ray_dir);
-}
-
-/**
- * Struct that kepts basic information about a BVHTree build from a editmesh.
- */
-typedef struct BVHTreeFromMeshType {
- void *userdata;
- char type;
-} BVHTreeFromMeshType;
-
/**
* Generates a struct with the immutable parameters that will be used on all objects.
*
@@ -286,52 +271,42 @@ static void snap_data_set(
copy_v2_v2(snapdata->depth_range, depth_range);
}
-static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3])
+MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3])
{
- switch (meshdata->type) {
- case SNAP_MESH:
- {
- BVHTreeFromMesh *data = meshdata->userdata;
- const MVert *vert = data->vert + index;
- normal_short_to_float_v3(r_no, vert->no);
- break;
- }
- case SNAP_EDIT_MESH:
- {
- BVHTreeFromEditMesh *data = meshdata->userdata;
- BMVert *eve = BM_vert_at_index(data->em->bm, index);
- copy_v3_v3(r_no, eve->no);
- break;
- }
- }
+ float dvec[3];
+ sub_v3_v3v3(dvec, co, ray_start);
+ return dot_v3v3(dvec, ray_dir);
}
-static void get_edge_verts(
- const BVHTreeFromMeshType *meshdata, const int index,
- const float *v_pair[2])
+static void copy_dm_vert_no(const int index, float r_no[3], const BVHTreeFromMesh *data)
{
- switch (meshdata->type) {
- case SNAP_MESH:
- {
- BVHTreeFromMesh *data = meshdata->userdata;
+ const MVert *vert = data->vert + index;
- const MVert *vert = data->vert;
- const MEdge *edge = data->edge + index;
+ normal_short_to_float_v3(r_no, vert->no);
+}
- v_pair[0] = vert[edge->v1].co;
- v_pair[1] = vert[edge->v2].co;
- break;
- }
- case SNAP_EDIT_MESH:
- {
- BVHTreeFromEditMesh *data = meshdata->userdata;
- BMEdge *eed = BM_edge_at_index(data->em->bm, index);
+static void copy_bvert_no(const int index, float r_no[3], const BVHTreeFromEditMesh *data)
+{
+ BMVert *eve = BM_vert_at_index(data->em->bm, index);
- v_pair[0] = eed->v1->co;
- v_pair[1] = eed->v2->co;
- break;
- }
- }
+ copy_v3_v3(r_no, eve->no);
+}
+
+static void get_dm_edge_verts(const int index, const float *v_pair[2], const BVHTreeFromMesh *data)
+{
+ const MVert *vert = data->vert;
+ const MEdge *edge = data->edge + index;
+
+ v_pair[0] = vert[edge->v1].co;
+ v_pair[1] = vert[edge->v2].co;
+}
+
+static void get_bedge_verts(const int index, const float *v_pair[2], const BVHTreeFromEditMesh *data)
+{
+ BMEdge *eed = BM_edge_at_index(data->em->bm, index);
+
+ v_pair[0] = eed->v1->co;
+ v_pair[1] = eed->v2->co;
}
static bool test_projected_vert_dist(
@@ -422,6 +397,7 @@ static void dist_squared_to_projected_aabb_precalc(
}
}
+/* Returns the distance from a 2d coordinate to a BoundBox (Projected) */
static float dist_squared_to_projected_aabb(
struct Nearest2dPrecalc *data,
const float bbmin[3], const float bbmax[3],
@@ -644,6 +620,10 @@ static float dist_aabb_to_plane(
/** \Walk DFS
* \{ */
+
+typedef void (*Nearest2DGetEdgeVertsCallback)(const int index, const float *v_pair[2], void *data);
+typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data);
+
typedef struct Nearest2dUserData {
struct Nearest2dPrecalc data_precalc;
@@ -652,7 +632,11 @@ typedef struct Nearest2dUserData {
bool r_axis_closest[3];
float depth_range[2];
+
void *userdata;
+ Nearest2DGetEdgeVertsCallback get_edge_verts;
+ Nearest2DCopyVertNoCallback copy_vert_no;
+
int index;
float co[3];
float no[3];
@@ -688,7 +672,7 @@ static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, vo
&data->dist_px_sq,
data->co))
{
- copy_vert_no(data->userdata, index, data->no);
+ data->copy_vert_no(index, data->no, data->userdata);
data->index = index;
}
return true;
@@ -700,7 +684,7 @@ static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int i
struct Nearest2dPrecalc *neasrest_precalc = &data->data_precalc;
const float *v_pair[2];
- get_edge_verts(data->userdata, index, v_pair);
+ data->get_edge_verts(index, v_pair, data->userdata);
if (test_projected_edge_dist(
data->depth_range,
@@ -1067,7 +1051,6 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
static bool snapDerivedMesh(
SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
- bool do_bb,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1092,274 +1075,258 @@ static bool snapDerivedMesh(
}
}
- {
- bool need_ray_start_correction_init =
- (snapdata->snap_to == SCE_SNAP_MODE_FACE) &&
- (snapdata->view_proj == VIEW_PROJ_ORTHO);
-
- float imat[4][4];
- float timat[3][3]; /* transpose inverse matrix for normals */
- float ray_start_local[3], ray_normal_local[3];
- float local_scale, local_depth, len_diff;
-
- invert_m4_m4(imat, obmat);
- transpose_m3_m4(timat, imat);
-
- copy_v3_v3(ray_start_local, snapdata->ray_start);
- copy_v3_v3(ray_normal_local, snapdata->ray_dir);
+ bool need_ray_start_correction_init =
+ (snapdata->snap_to == SCE_SNAP_MODE_FACE) &&
+ (snapdata->view_proj == VIEW_PROJ_ORTHO);
- mul_m4_v3(imat, ray_start_local);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff;
- /* local scale in normal direction */
- local_scale = normalize_v3(ray_normal_local);
- local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
+ invert_m4_m4(imat, obmat);
+ transpose_m3_m4(timat, imat);
- float lpmat[4][4];
- float ray_org_local[3];
- float ray_min_dist;
- if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- ray_min_dist = snapdata->depth_range[0] * local_scale;
- }
+ copy_v3_v3(ray_start_local, snapdata->ray_start);
+ copy_v3_v3(ray_normal_local, snapdata->ray_dir);
- copy_v3_v3(ray_org_local, snapdata->ray_origin);
- mul_m4_v3(imat, ray_org_local);
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
- if (do_bb) {
- BoundBox *bb = BKE_object_boundbox_get(ob);
+ /* local scale in normal direction */
+ local_scale = normalize_v3(ray_normal_local);
+ local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
- if (bb) {
- BoundBox bb_temp;
+ float lpmat[4][4];
+ float ray_org_local[3];
+ float ray_min_dist;
+ if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ ray_min_dist = snapdata->depth_range[0] * local_scale;
+ }
- /* We cannot afford a bounding box with some null dimension, which may happen in some cases...
- * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
- bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
+ mul_m4_v3(imat, ray_org_local);
- /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */
- if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
- float dist_px_sq = dist_squared_to_projected_aabb_simple(
- lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
- ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
- if (dist_px_sq > SQUARE(*dist_px))
- {
- return retval;
- }
- }
- else {
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL))
- {
- return retval;
- }
- }
- /* was local_depth, see: T47838 */
- len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local);
- if (len_diff < 0) len_diff = 0.0f;
- need_ray_start_correction_init = false;
+ /* Test BoundBox */
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+ if (bb) {
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
+ if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
+ float dist_px_sq = dist_squared_to_projected_aabb_simple(
+ lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
+ ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
+ if (dist_px_sq > SQUARE(*dist_px))
+ {
+ return retval;
}
}
-
- SnapObjectData_Mesh *sod = NULL;
- BVHTreeFromMesh *treedata = NULL, treedata_stack;
-
- if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
- sod = *sod_p;
- }
- else {
- sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_MESH;
+ else {
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL))
+ {
+ return retval;
}
+ }
+ /* was local_depth, see: T47838 */
+ len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local);
+ if (len_diff < 0) len_diff = 0.0f;
+ need_ray_start_correction_init = false;
+ }
- int tree_index = -1;
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- tree_index = 2;
- break;
- case SCE_SNAP_MODE_EDGE:
- tree_index = 1;
- break;
- case SCE_SNAP_MODE_VERTEX:
- tree_index = 0;
- break;
- }
- if (tree_index != -1) {
- if (sod->bvh_trees[tree_index] == NULL) {
- sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
- }
- treedata = sod->bvh_trees[tree_index];
+ SnapObjectData_Mesh *sod = NULL;
+ BVHTreeFromMesh *treedata = NULL;
- /* the tree is owned by the DM and may have been freed since we last used! */
- if (treedata && treedata->tree) {
- if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) {
- free_bvhtree_from_mesh(treedata);
- }
- }
- }
- }
- else {
- treedata = &treedata_stack;
- memset(treedata, 0, sizeof(*treedata));
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ sod = *sod_p;
+ }
+ else {
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_MESH;
+ }
+
+ int tree_index = -1;
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ tree_index = 2;
+ break;
+ case SCE_SNAP_MODE_EDGE:
+ tree_index = 1;
+ break;
+ case SCE_SNAP_MODE_VERTEX:
+ tree_index = 0;
+ break;
+ }
+ if (tree_index != -1) {
+ if (sod->bvh_trees[tree_index] == NULL) {
+ sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
}
+ treedata = sod->bvh_trees[tree_index];
- if (treedata && treedata->tree == NULL) {
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
- break;
- case SCE_SNAP_MODE_EDGE:
- bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6);
- break;
- case SCE_SNAP_MODE_VERTEX:
- bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6);
- break;
+ /* the tree is owned by the DM and may have been freed since we last used! */
+ if (treedata && treedata->tree) {
+ if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) {
+ free_bvhtree_from_mesh(treedata);
}
}
+ }
- if (!treedata || !treedata->tree) {
- return retval;
+ if (treedata && treedata->tree == NULL) {
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
+ break;
+ case SCE_SNAP_MODE_EDGE:
+ bvhtree_from_mesh_edges(treedata, dm, 0.0f, 2, 6);
+ break;
+ case SCE_SNAP_MODE_VERTEX:
+ bvhtree_from_mesh_verts(treedata, dm, 0.0f, 2, 6);
+ break;
}
+ }
+ if (!treedata || !treedata->tree) {
+ return retval;
+ }
- if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
- /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
- * been *inside* boundbox, leading to snap failures (see T38409).
- * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
- */
- if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
- if (need_ray_start_correction_init) {
- /* We *need* a reasonably valid len_diff in this case.
- * Use BHVTree to find the closest face from ray_start_local.
- */
- BVHTreeNearest nearest;
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
- /* Compute and store result. */
- BLI_bvhtree_find_nearest(
- treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata);
- if (nearest.index != -1) {
- float dvec[3];
- sub_v3_v3v3(dvec, nearest.co, ray_start_local);
- len_diff = dot_v3v3(dvec, ray_normal_local);
- }
- }
- /* You need to make sure that ray_start is really far away,
- * because even in the Orthografic view, in some cases,
- * the ray can start inside the object (see T50486) */
- if (len_diff > 400.0f) {
- /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
- * very far away ray_start values (as returned in case of ortho view3d), see T38358.
- */
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3v3fl(
- ray_start_local, ray_org_local, ray_normal_local,
- len_diff + snapdata->depth_range[0] * local_scale);
- local_depth -= len_diff;
+ if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
+ /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
+ * been *inside* boundbox, leading to snap failures (see T38409).
+ * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
+ */
+ if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
+ if (need_ray_start_correction_init) {
+ /* We *need* a reasonably valid len_diff in this case.
+ * Use BHVTree to find the closest face from ray_start_local.
+ */
+ BVHTreeNearest nearest;
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+ /* Compute and store result. */
+ BLI_bvhtree_find_nearest(
+ treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata);
+ if (nearest.index != -1) {
+ float dvec[3];
+ sub_v3_v3v3(dvec, nearest.co, ray_start_local);
+ len_diff = dot_v3v3(dvec, ray_normal_local);
}
- else len_diff = 0.0f;
}
- else {
- len_diff = 0.0f;
- }
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
+ /* You need to make sure that ray_start is really far away,
+ * because even in the Orthografic view, in some cases,
+ * the ray can start inside the object (see T50486) */
+ if (len_diff > 400.0f) {
+ /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with
+ * very far away ray_start values (as returned in case of ortho view3d), see T38358.
+ */
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3v3fl(
+ ray_start_local, ray_org_local, ray_normal_local,
+ len_diff + snapdata->depth_range[0] * local_scale);
+ local_depth -= len_diff;
}
- else {
- BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
+ else len_diff = 0.0f;
+ }
+ else {
+ len_diff = 0.0f;
+ }
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ *ray_depth, raycast_all_cb, &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
+ if (BLI_bvhtree_ray_cast(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
- retval = true;
+ retval = true;
- if (r_index) {
- *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
- }
+ if (r_index) {
+ *r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
}
}
}
}
- /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */
- else {
- BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH};
-
- Nearest2dUserData neasrest2d = {
- .dist_px_sq = SQUARE(*dist_px),
- .r_axis_closest = {1.0f, 1.0f, 1.0f},
- .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
- .userdata = &treedata_type,
- .index = -1};
-
- dist_squared_to_projected_aabb_precalc(
- &neasrest2d.data_precalc, lpmat,
- snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
- ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local);
-
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
-
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
-
- if (neasrest2d.index != -1) {
- copy_v3_v3(r_loc, neasrest2d.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, neasrest2d.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
- *dist_px = sqrtf(neasrest2d.dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ }
+ /* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */
+ else {
- retval = true;
+ /* Warning: the depth_max is currently being used only in perspective view.
+ * It is not correct to limit the maximum depth for elements obtained with nearest
+ * since this limitation depends on the normal and the size of the occlusion face.
+ * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */
+ const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0];
+
+ Nearest2dUserData neasrest2d = {
+ .dist_px_sq = SQUARE(*dist_px),
+ .r_axis_closest = {1.0f, 1.0f, 1.0f},
+ .depth_range = {snapdata->depth_range[0], ray_depth_max_global},
+ .userdata = treedata,
+ .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no,
+ .index = -1};
+
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest2d.data_precalc, lpmat,
+ snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
+ ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local);
+
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
+
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
+
+ if (neasrest2d.index != -1) {
+ copy_v3_v3(r_loc, neasrest2d.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest2d.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
}
- }
+ *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
- if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) {
- if (treedata) {
- free_bvhtree_from_mesh(treedata);
- }
+ retval = true;
}
}
@@ -1393,268 +1360,246 @@ static bool snapEditMesh(
}
}
- {
- float imat[4][4];
- float timat[3][3]; /* transpose inverse matrix for normals */
- float ray_normal_local[3];
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_normal_local[3];
- invert_m4_m4(imat, obmat);
- transpose_m3_m4(timat, imat);
+ invert_m4_m4(imat, obmat);
+ transpose_m3_m4(timat, imat);
- copy_v3_v3(ray_normal_local, snapdata->ray_dir);
+ copy_v3_v3(ray_normal_local, snapdata->ray_dir);
- mul_mat3_m4_v3(imat, ray_normal_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
- /* local scale in normal direction */
- float local_scale = normalize_v3(ray_normal_local);
- float local_depth = *ray_depth;
- if (local_depth != BVH_RAYCAST_DIST_MAX) {
- local_depth *= local_scale;
- }
+ /* local scale in normal direction */
+ float local_scale = normalize_v3(ray_normal_local);
+ float local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
- SnapObjectData_EditMesh *sod = NULL;
+ SnapObjectData_EditMesh *sod = NULL;
- BVHTreeFromEditMesh *treedata = NULL, treedata_stack;
+ BVHTreeFromEditMesh *treedata = NULL;
- if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
- sod = *sod_p;
- }
- else {
- sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_EDIT_MESH;
- }
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ sod = *sod_p;
+ }
+ else {
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_EDIT_MESH;
+ }
- int tree_index = -1;
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- tree_index = 2;
- break;
- case SCE_SNAP_MODE_EDGE:
- tree_index = 1;
- break;
- case SCE_SNAP_MODE_VERTEX:
- tree_index = 0;
- break;
- }
- if (tree_index != -1) {
- if (sod->bvh_trees[tree_index] == NULL) {
- sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
- }
- treedata = sod->bvh_trees[tree_index];
- }
- }
- else {
- treedata = &treedata_stack;
- memset(treedata, 0, sizeof(*treedata));
+ int tree_index = -1;
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ tree_index = 2;
+ break;
+ case SCE_SNAP_MODE_EDGE:
+ tree_index = 1;
+ break;
+ case SCE_SNAP_MODE_VERTEX:
+ tree_index = 0;
+ break;
+ }
+ if (tree_index != -1) {
+ if (sod->bvh_trees[tree_index] == NULL) {
+ sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
}
+ treedata = sod->bvh_trees[tree_index];
+ }
- if (treedata && treedata->tree == NULL) {
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_FACE:
- {
- BLI_bitmap *looptri_mask = NULL;
- int looptri_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_face_fn) {
- looptri_mask = BLI_BITMAP_NEW(em->tottri, __func__);
- looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
- em->bm, looptri_mask,
- sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
- }
- bvhtree_from_editmesh_looptri_ex(treedata, em, looptri_mask, looptri_num_active, 0.0f, 4, 6, NULL);
- if (looptri_mask) {
- MEM_freeN(looptri_mask);
- }
- break;
+ if (treedata && treedata->tree == NULL) {
+ BLI_bitmap *elem_mask = NULL;
+ switch (snapdata->snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ {
+ int looptri_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_face_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->tottri, __func__);
+ looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
+ em->bm, elem_mask,
+ sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
}
- case SCE_SNAP_MODE_EDGE:
- {
- BLI_bitmap *edges_mask = NULL;
- int edges_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_edge_fn) {
- edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
- edges_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_EDGES_OF_MESH, em->bm, edges_mask,
- (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- bvhtree_from_editmesh_edges_ex(treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6);
- if (edges_mask) {
- MEM_freeN(edges_mask);
- }
- break;
+ bvhtree_from_editmesh_looptri_ex(treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, NULL);
+ break;
+ }
+ case SCE_SNAP_MODE_EDGE:
+ {
+ int edges_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_edge_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
+ edges_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_EDGES_OF_MESH, em->bm, elem_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
+ sctx->callbacks.edit_mesh.user_data);
}
- case SCE_SNAP_MODE_VERTEX:
- {
- BLI_bitmap *verts_mask = NULL;
- int verts_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_vert_fn) {
- verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
- verts_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_VERTS_OF_MESH, em->bm, verts_mask,
- (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- bvhtree_from_editmesh_verts_ex(treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6);
- if (verts_mask) {
- MEM_freeN(verts_mask);
- }
- break;
+ bvhtree_from_editmesh_edges_ex(treedata, em, elem_mask, edges_num_active, 0.0f, 2, 6);
+ break;
+ }
+ case SCE_SNAP_MODE_VERTEX:
+ {
+ int verts_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_vert_fn) {
+ elem_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
+ verts_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_VERTS_OF_MESH, em->bm, elem_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
+ sctx->callbacks.edit_mesh.user_data);
}
+ bvhtree_from_editmesh_verts_ex(treedata, em, elem_mask, verts_num_active, 0.0f, 2, 6);
+ break;
}
}
-
- if (!treedata || !treedata->tree) {
- return retval;
+ if (elem_mask) {
+ MEM_freeN(elem_mask);
}
+ }
- if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
- float ray_start_local[3];
- copy_v3_v3(ray_start_local, snapdata->ray_start);
- mul_m4_v3(imat, ray_start_local);
+ if (!treedata || !treedata->tree) {
+ return retval;
+ }
- /* Only use closer ray_start in case of ortho view! In perspective one, ray_start
- * may already been *inside* boundbox, leading to snap failures (see T38409).
- * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
+ if (snapdata->snap_to == SCE_SNAP_MODE_FACE) {
+ float ray_start_local[3];
+ copy_v3_v3(ray_start_local, snapdata->ray_start);
+ mul_m4_v3(imat, ray_start_local);
+
+ /* Only use closer ray_start in case of ortho view! In perspective one, ray_start
+ * may already been *inside* boundbox, leading to snap failures (see T38409).
+ * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
+ */
+ float len_diff = 0.0f;
+ if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
+ /* We *need* a reasonably valid len_diff in this case.
+ * Use BHVTree to find the closest face from ray_start_local.
*/
- float len_diff = 0.0f;
- if (snapdata->view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */
- /* We *need* a reasonably valid len_diff in this case.
- * Use BHVTree to find the closest face from ray_start_local.
- */
- BVHTreeNearest nearest;
- nearest.index = -1;
- nearest.dist_sq = FLT_MAX;
- /* Compute and store result. */
- if (BLI_bvhtree_find_nearest(
- treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1)
- {
- float dvec[3];
- sub_v3_v3v3(dvec, nearest.co, ray_start_local);
- len_diff = dot_v3v3(dvec, ray_normal_local);
- /* You need to make sure that ray_start is really far away,
- * because even in the Orthografic view, in some cases,
- * the ray can start inside the object (see T50486) */
- if (len_diff > 400.0f) {
- float ray_org_local[3];
-
- copy_v3_v3(ray_org_local, snapdata->ray_origin);
- mul_m4_v3(imat, ray_org_local);
-
- /* We pass a temp ray_start, set from object's boundbox,
- * to avoid precision issues with very far away ray_start values
- * (as returned in case of ortho view3d), see T38358.
- */
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3v3fl(
- ray_start_local, ray_org_local, ray_normal_local,
- len_diff + snapdata->depth_range[0] * local_scale);
- local_depth -= len_diff;
- }
- else len_diff = 0.0f;
+ BVHTreeNearest nearest;
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+ /* Compute and store result. */
+ if (BLI_bvhtree_find_nearest(
+ treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1)
+ {
+ float dvec[3];
+ sub_v3_v3v3(dvec, nearest.co, ray_start_local);
+ len_diff = dot_v3v3(dvec, ray_normal_local);
+ /* You need to make sure that ray_start is really far away,
+ * because even in the Orthografic view, in some cases,
+ * the ray can start inside the object (see T50486) */
+ if (len_diff > 400.0f) {
+ float ray_org_local[3];
+
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
+ mul_m4_v3(imat, ray_org_local);
+
+ /* We pass a temp ray_start, set from object's boundbox,
+ * to avoid precision issues with very far away ray_start values
+ * (as returned in case of ortho view3d), see T38358.
+ */
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3v3fl(
+ ray_start_local, ray_org_local, ray_normal_local,
+ len_diff + snapdata->depth_range[0] * local_scale);
+ local_depth -= len_diff;
}
+ else len_diff = 0.0f;
}
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
+ }
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ *ray_depth, raycast_all_cb, &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {.index = -1, .dist = local_depth};
- if (BLI_bvhtree_ray_cast(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- &hit, treedata->raycast_callback, treedata) != -1)
- {
- hit.dist += len_diff;
- hit.dist /= local_scale;
- if (hit.dist <= *ray_depth) {
- *ray_depth = hit.dist;
- copy_v3_v3(r_loc, hit.co);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
+ if (BLI_bvhtree_ray_cast(
+ treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
- retval = true;
+ retval = true;
- if (r_index) {
- *r_index = hit.index;
- }
+ if (r_index) {
+ *r_index = hit.index;
}
}
}
}
- else {
- float ray_org_local[3];
- copy_v3_v3(ray_org_local, snapdata->ray_origin);
- mul_m4_v3(imat, ray_org_local);
-
- BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH};
-
- Nearest2dUserData neasrest2d = {
- .dist_px_sq = SQUARE(*dist_px),
- .r_axis_closest = {1.0f, 1.0f, 1.0f},
- .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
- .userdata = &treedata_type,
- .index = -1};
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
- dist_squared_to_projected_aabb_precalc(
- &neasrest2d.data_precalc, lpmat,
- snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
- (snapdata->depth_range[0] * local_scale), snapdata->mval,
- ray_org_local, ray_normal_local);
-
- BVHTree_WalkLeafCallback cb_walk_leaf =
- (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
- cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
-
- BLI_bvhtree_walk_dfs(
- treedata->tree,
- cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
-
- if (neasrest2d.index != -1) {
- copy_v3_v3(r_loc, neasrest2d.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- copy_v3_v3(r_no, neasrest2d.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
- *dist_px = sqrtf(neasrest2d.dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ }
+ else {
+ float ray_org_local[3];
+ copy_v3_v3(ray_org_local, snapdata->ray_origin);
+ mul_m4_v3(imat, ray_org_local);
- retval = true;
- }
- }
+ Nearest2dUserData neasrest2d = {
+ .dist_px_sq = SQUARE(*dist_px),
+ .r_axis_closest = {1.0f, 1.0f, 1.0f},
+ .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
+ .userdata = treedata,
+ .get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_bedge_verts,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)copy_bvert_no,
+ .index = -1};
- if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) {
- if (treedata) {
- free_bvhtree_from_editmesh(treedata);
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest2d.data_precalc, lpmat,
+ snapdata->view_proj == VIEW_PROJ_PERSP, snapdata->win_half,
+ (snapdata->depth_range[0] * local_scale), snapdata->mval,
+ ray_org_local, ray_normal_local);
+
+ BVHTree_WalkLeafCallback cb_walk_leaf =
+ (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ?
+ cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge;
+
+ BLI_bvhtree_walk_dfs(
+ treedata->tree,
+ cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest2d);
+
+ if (neasrest2d.index != -1) {
+ copy_v3_v3(r_loc, neasrest2d.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ copy_v3_v3(r_no, neasrest2d.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
}
+ *dist_px = sqrtf(neasrest2d.dist_px_sq);
+ *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+
+ retval = true;
}
}
@@ -1703,7 +1648,6 @@ static bool snapObject(
}
retval = snapDerivedMesh(
sctx, snapdata, ob, dm, obmat, ob_index,
- true,
ray_depth, dist_px,
r_loc, r_no,
r_index, r_hit_list);
@@ -1880,6 +1824,9 @@ SnapObjectContext *ED_transform_snap_object_context_create(
sctx->bmain = bmain;
sctx->scene = scene;
+ sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
+ sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+
return sctx;
}
@@ -1894,11 +1841,6 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d(
sctx->v3d_data.ar = ar;
sctx->v3d_data.v3d = v3d;
- if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
- sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
- sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- }
-
return sctx;
}
@@ -1930,10 +1872,8 @@ static void snap_object_data_free(void *sod_v)
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
{
- if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
- BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
- BLI_memarena_free(sctx->cache.mem_arena);
- }
+ BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
+ BLI_memarena_free(sctx->cache.mem_arena);
MEM_freeN(sctx);
}
@@ -1956,7 +1896,7 @@ bool ED_transform_snap_object_project_ray_ex(
SnapObjectContext *sctx,
const unsigned short snap_to,
const struct SnapObjectParams *params,
- const float UNUSED(ray_start[3]), const float UNUSED(ray_normal[3]),
+ const float ray_start[3], const float ray_normal[3],
float *ray_depth,
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
@@ -1964,7 +1904,9 @@ bool ED_transform_snap_object_project_ray_ex(
const float depth_range[2] = {0.0f, FLT_MAX};
SnapData snapdata;
- snap_data_set(&snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE, NULL, r_loc, r_loc, r_no, depth_range);
+ snap_data_set(
+ &snapdata, sctx->v3d_data.ar, snap_to, VIEW_PROJ_NONE,
+ NULL, ray_start, ray_start, ray_normal, depth_range);
return snapObjectsRay(
sctx, &snapdata,
@@ -2083,11 +2025,13 @@ static bool transform_snap_context_project_view3d_mixed_impl(
BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0);
if (use_depth) {
- const float dist_px_orig = *dist_px;
+ const float dist_px_orig = dist_px ? *dist_px : 0;
for (int i = 2; i >= 0; i--) {
if (snap_to_flag & (1 << i)) {
- if (i == 0)
+ if (i == 0) {
+ BLI_assert(dist_px != NULL);
*dist_px = dist_px_orig;
+ }
if (ED_transform_snap_object_project_view3d(
sctx,
elem_type[i], params,
diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h
index 52febe642a0..4164f5fa75d 100644
--- a/source/blender/imbuf/IMB_colormanagement.h
+++ b/source/blender/imbuf/IMB_colormanagement.h
@@ -77,6 +77,16 @@ void IMB_colormanagement_transform(float *buffer, int width, int height, int cha
const char *from_colorspace, const char *to_colorspace, bool predivide);
void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels,
const char *from_colorspace, const char *to_colorspace, bool predivide);
+void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace);
+void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace);
+void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer,
+ int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace);
+void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer,
+ int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace);
void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace);
void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], struct ColorSpace *colorspace);
@@ -185,6 +195,8 @@ void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_proc
void IMB_colormanagement_processor_apply_pixel(struct ColormanageProcessor *cm_processor, float *pixel, int channels);
void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height,
int channels, bool predivide);
+void IMB_colormanagement_processor_apply_byte(struct ColormanageProcessor *cm_processor,
+ unsigned char *buffer, int width, int height, int channels);
void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor);
/* ** OpenGL drawing routines using GLSL for color space transform ** */
diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c
index a45346279d9..48cba3e0800 100644
--- a/source/blender/imbuf/intern/colormanagement.c
+++ b/source/blender/imbuf/intern/colormanagement.c
@@ -1555,21 +1555,25 @@ static void colormanage_display_buffer_process(ImBuf *ibuf, unsigned char *displ
typedef struct ProcessorTransformThread {
ColormanageProcessor *cm_processor;
- float *buffer;
+ unsigned char *byte_buffer;
+ float *float_buffer;
int width;
int start_line;
int tot_line;
int channels;
bool predivide;
+ bool float_from_byte;
} ProcessorTransformThread;
typedef struct ProcessorTransformInit {
ColormanageProcessor *cm_processor;
- float *buffer;
+ unsigned char *byte_buffer;
+ float *float_buffer;
int width;
int height;
int channels;
bool predivide;
+ bool float_from_byte;
} ProcessorTransformInitData;
static void processor_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
@@ -1577,17 +1581,24 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int
ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v;
ProcessorTransformInitData *init_data = (ProcessorTransformInitData *) init_data_v;
- int channels = init_data->channels;
- int width = init_data->width;
- bool predivide = init_data->predivide;
+ const int channels = init_data->channels;
+ const int width = init_data->width;
+ const bool predivide = init_data->predivide;
+ const bool float_from_byte = init_data->float_from_byte;
- size_t offset = ((size_t)channels) * start_line * width;
+ const size_t offset = ((size_t)channels) * start_line * width;
memset(handle, 0, sizeof(ProcessorTransformThread));
handle->cm_processor = init_data->cm_processor;
- handle->buffer = init_data->buffer + offset;
+ if (init_data->byte_buffer != NULL) {
+ /* TODO(serge): Offset might be different for byte and float buffers. */
+ handle->byte_buffer = init_data->byte_buffer + offset;
+ }
+ if (init_data->float_buffer != NULL) {
+ handle->float_buffer = init_data->float_buffer + offset;
+ }
handle->width = width;
@@ -1596,33 +1607,62 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int
handle->channels = channels;
handle->predivide = predivide;
+ handle->float_from_byte = float_from_byte;
}
static void *do_processor_transform_thread(void *handle_v)
{
ProcessorTransformThread *handle = (ProcessorTransformThread *) handle_v;
- float *buffer = handle->buffer;
- int channels = handle->channels;
- int width = handle->width;
- int height = handle->tot_line;
- bool predivide = handle->predivide;
-
- IMB_colormanagement_processor_apply(handle->cm_processor, buffer, width, height, channels, predivide);
+ unsigned char *byte_buffer = handle->byte_buffer;
+ float *float_buffer = handle->float_buffer;
+ const int channels = handle->channels;
+ const int width = handle->width;
+ const int height = handle->tot_line;
+ const bool predivide = handle->predivide;
+ const bool float_from_byte = handle->float_from_byte;
+
+ if (float_from_byte) {
+ IMB_buffer_float_from_byte(float_buffer, byte_buffer,
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ true,
+ width, height, width, width);
+ IMB_colormanagement_processor_apply(handle->cm_processor,
+ float_buffer,
+ width, height, channels,
+ predivide);
+ }
+ else {
+ if (byte_buffer != NULL) {
+ IMB_colormanagement_processor_apply_byte(handle->cm_processor,
+ byte_buffer,
+ width, height, channels);
+ }
+ if (float_buffer != NULL) {
+ IMB_colormanagement_processor_apply(handle->cm_processor,
+ float_buffer,
+ width, height, channels,
+ predivide);
+ }
+ }
return NULL;
}
-static void processor_transform_apply_threaded(float *buffer, int width, int height, int channels,
- ColormanageProcessor *cm_processor, bool predivide)
+static void processor_transform_apply_threaded(unsigned char *byte_buffer, float *float_buffer,
+ const int width, const int height, const int channels,
+ ColormanageProcessor *cm_processor,
+ const bool predivide, const bool float_from_byte)
{
ProcessorTransformInitData init_data;
init_data.cm_processor = cm_processor;
- init_data.buffer = buffer;
+ init_data.byte_buffer = byte_buffer;
+ init_data.float_buffer = float_buffer;
init_data.width = width;
init_data.height = height;
init_data.channels = channels;
init_data.predivide = predivide;
+ init_data.float_from_byte = float_from_byte;
IMB_processor_apply_threaded(height, sizeof(ProcessorTransformThread), &init_data,
processor_transform_init_handle, do_processor_transform_thread);
@@ -1631,8 +1671,10 @@ static void processor_transform_apply_threaded(float *buffer, int width, int hei
/*********************** Color space transformation functions *************************/
/* convert the whole buffer from specified by name color space to another - internal implementation */
-static void colormanagement_transform_ex(float *buffer, int width, int height, int channels, const char *from_colorspace,
- const char *to_colorspace, bool predivide, bool do_threaded)
+static void colormanagement_transform_ex(unsigned char *byte_buffer, float *float_buffer,
+ int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace,
+ bool predivide, bool do_threaded)
{
ColormanageProcessor *cm_processor;
@@ -1649,10 +1691,19 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i
cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace);
- if (do_threaded)
- processor_transform_apply_threaded(buffer, width, height, channels, cm_processor, predivide);
- else
- IMB_colormanagement_processor_apply(cm_processor, buffer, width, height, channels, predivide);
+ if (do_threaded) {
+ processor_transform_apply_threaded(byte_buffer, float_buffer,
+ width, height, channels,
+ cm_processor, predivide, false);
+ }
+ else {
+ if (byte_buffer != NULL) {
+ IMB_colormanagement_processor_apply_byte(cm_processor, byte_buffer, width, height, channels);
+ }
+ if (float_buffer != NULL) {
+ IMB_colormanagement_processor_apply(cm_processor, float_buffer, width, height, channels, predivide);
+ }
+ }
IMB_colormanagement_processor_free(cm_processor);
}
@@ -1661,7 +1712,7 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i
void IMB_colormanagement_transform(float *buffer, int width, int height, int channels,
const char *from_colorspace, const char *to_colorspace, bool predivide)
{
- colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false);
+ colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false);
}
/* convert the whole buffer from specified by name color space to another
@@ -1670,7 +1721,54 @@ void IMB_colormanagement_transform(float *buffer, int width, int height, int cha
void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels,
const char *from_colorspace, const char *to_colorspace, bool predivide)
{
- colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true);
+ colormanagement_transform_ex(NULL, buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true);
+}
+
+/* Similar to functions above, but operates on byte buffer. */
+void IMB_colormanagement_transform_byte(unsigned char *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace)
+{
+ colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, false);
+}
+void IMB_colormanagement_transform_byte_threaded(unsigned char *buffer, int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace)
+{
+ colormanagement_transform_ex(buffer, NULL, width, height, channels, from_colorspace, to_colorspace, false, true);
+}
+
+/* Similar to above, but gets float buffer from display one. */
+void IMB_colormanagement_transform_from_byte(float *float_buffer, unsigned char *byte_buffer,
+ int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace)
+{
+ IMB_buffer_float_from_byte(float_buffer, byte_buffer,
+ IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+ true,
+ width, height, width, width);
+ IMB_colormanagement_transform(float_buffer,
+ width, height, channels,
+ from_colorspace, to_colorspace,
+ true);
+}
+void IMB_colormanagement_transform_from_byte_threaded(float *float_buffer, unsigned char *byte_buffer,
+ int width, int height, int channels,
+ const char *from_colorspace, const char *to_colorspace)
+{
+ ColormanageProcessor *cm_processor;
+ if (from_colorspace == NULL || from_colorspace[0] == '\0') {
+ return;
+ }
+ if (STREQ(from_colorspace, to_colorspace)) {
+ /* If source and destination color spaces are identical, skip
+ * threading overhead and simply do nothing
+ */
+ return;
+ }
+ cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace);
+ processor_transform_apply_threaded(byte_buffer, float_buffer,
+ width, height, channels,
+ cm_processor, true, true);
+ IMB_colormanagement_processor_free(cm_processor);
}
void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace)
@@ -1974,12 +2072,14 @@ void IMB_colormanagement_buffer_make_display_space(float *buffer, unsigned char
size_t float_buffer_size = ((size_t)width) * height * channels * sizeof(float);
float *display_buffer_float = MEM_mallocN(float_buffer_size, "byte_buffer_make_display_space");
+ /* TODO(sergey): Convert float directly to byte buffer. */
+
memcpy(display_buffer_float, buffer, float_buffer_size);
cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings);
- processor_transform_apply_threaded(display_buffer_float, width, height, channels,
- cm_processor, true);
+ processor_transform_apply_threaded(NULL, display_buffer_float, width, height, channels,
+ cm_processor, true, false);
IMB_buffer_byte_from_float(display_buffer, display_buffer_float,
channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB,
@@ -3100,6 +3200,25 @@ void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, flo
}
}
+void IMB_colormanagement_processor_apply_byte(ColormanageProcessor *cm_processor,
+ unsigned char *buffer,
+ int width, int height, int channels)
+{
+ /* TODO(sergey): Would be nice to support arbitrary channels configurations,
+ * but for now it's not so important.
+ */
+ BLI_assert(channels == 4);
+ float pixel[4];
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ size_t offset = channels * (((size_t)y) * width + x);
+ rgba_uchar_to_float(pixel, buffer + offset);
+ IMB_colormanagement_processor_apply_v4(cm_processor, pixel);
+ rgba_float_to_uchar(buffer + offset, pixel);
+ }
+ }
+}
+
void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
{
if (cm_processor->curve_mapping)
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 8ee15ef21a3..918d0f00040 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1716,6 +1716,7 @@ typedef struct Scene {
#define SCER_LOCK_FRAME_SELECTION (1<<1)
/* timeline/keyframe jumping - only selected items (on by default) */
#define SCE_KEYS_NO_SELONLY (1<<2)
+#define SCER_SHOW_SUBFRAME (1<<3)
/* mode (int now) */
#define R_OSA 0x0001
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 1166fb89a0a..8ee49045bc5 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -792,6 +792,21 @@ static void rna_Scene_frame_current_set(PointerRNA *ptr, int value)
data->r.cfra = value;
}
+static float rna_Scene_frame_float_get(PointerRNA *ptr)
+{
+ Scene *data = (Scene *)ptr->data;
+ return (float)data->r.cfra + data->r.subframe;
+}
+
+static void rna_Scene_frame_float_set(PointerRNA *ptr, float value)
+{
+ Scene *data = (Scene *)ptr->data;
+ /* if negative frames aren't allowed, then we can't use them */
+ FRAMENUMBER_MIN_CLAMP(value);
+ data->r.cfra = (int)value;
+ data->r.subframe = value - data->r.cfra;
+}
+
static float rna_Scene_frame_current_final_get(PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
@@ -872,6 +887,12 @@ static void rna_Scene_preview_range_end_frame_set(PointerRNA *ptr, int value)
data->r.pefra = value;
}
+static void rna_Scene_show_subframe_update(Main *UNUSED(bmain), Scene *UNUSED(current_scene), PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ scene->r.subframe = 0.0f;
+}
+
static void rna_Scene_frame_update(Main *bmain, Scene *UNUSED(current_scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
@@ -7081,8 +7102,19 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_subframe", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "r.subframe");
RNA_def_property_ui_text(prop, "Current Sub-Frame", "");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
-
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 2);
+ RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update");
+
+ prop = RNA_def_property(srna, "frame_float", PROP_FLOAT, PROP_TIME);
+ RNA_def_property_ui_text(prop, "Current Sub-Frame", "");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
+ RNA_def_property_ui_range(prop, MINAFRAME, MAXFRAME, 0.1, 2);
+ RNA_def_property_float_funcs(prop, "rna_Scene_frame_float_get", "rna_Scene_frame_float_set", NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update");
+
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_sdna(prop, NULL, "r.sfra");
@@ -7147,7 +7179,15 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_int_funcs(prop, NULL, "rna_Scene_preview_range_end_frame_set", NULL);
RNA_def_property_ui_text(prop, "Preview Range End Frame", "Alternative end frame for UI playback");
RNA_def_property_update(prop, NC_SCENE | ND_FRAME, NULL);
-
+
+ /* Subframe for moblur debug. */
+ prop = RNA_def_property(srna, "show_subframe", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_boolean_sdna(prop, NULL, "r.flag", SCER_SHOW_SUBFRAME);
+ RNA_def_property_ui_text(prop, "Show Subframe",
+ "Show current scene subframe and allow set it using interface tools");
+ RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_show_subframe_update");
+
/* Timeline / Time Navigation settings */
prop = RNA_def_property(srna, "show_keys_from_selected_only", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SCE_KEYS_NO_SELONLY);
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 08d118a2026..f6acbef96e9 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -38,10 +38,12 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_task.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
+#include "BKE_image.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_texture.h"
@@ -200,21 +202,130 @@ static void updateDepsgraph(ModifierData *md,
}
}
+typedef struct DisplaceUserdata {
+ /*const*/ DisplaceModifierData *dmd;
+ struct ImagePool *pool;
+ MDeformVert *dvert;
+ float weight;
+ int defgrp_index;
+ int direction;
+ bool use_global_direction;
+ float (*tex_co)[3];
+ float (*vertexCos)[3];
+ float local_mat[4][4];
+ MVert *mvert;
+ float (*vert_clnors)[3];
+} DisplaceUserdata;
+
+static void displaceModifier_do_task(void *userdata, const int iter)
+{
+ DisplaceUserdata *data = (DisplaceUserdata *)userdata;
+ DisplaceModifierData *dmd = data->dmd;
+ MDeformVert *dvert = data->dvert;
+ float weight = data->weight;
+ int defgrp_index = data->defgrp_index;
+ int direction = data->direction;
+ bool use_global_direction = data->use_global_direction;
+ float (*tex_co)[3] = data->tex_co;
+ float (*vertexCos)[3] = data->vertexCos;
+ MVert *mvert = data->mvert;
+ float (*vert_clnors)[3] = data->vert_clnors;
+
+ const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */
+
+ TexResult texres;
+ float strength = dmd->strength;
+ float delta;
+ float local_vec[3];
+
+ if (dvert) {
+ weight = defvert_find_weight(dvert + iter, defgrp_index);
+ if (weight == 0.0f) {
+ return;
+ }
+ }
+
+ if (dmd->texture) {
+ texres.nor = NULL;
+ BKE_texture_get_value_ex(dmd->modifier.scene, dmd->texture, tex_co[iter], &texres, data->pool, false);
+ delta = texres.tin - dmd->midlevel;
+ }
+ else {
+ delta = delta_fixed; /* (1.0f - dmd->midlevel) */ /* never changes */
+ }
+
+ if (dvert) {
+ strength *= weight;
+ }
+
+ delta *= strength;
+ CLAMP(delta, -10000, 10000);
+
+ switch (direction) {
+ case MOD_DISP_DIR_X:
+ if (use_global_direction) {
+ vertexCos[iter][0] += delta * data->local_mat[0][0];
+ vertexCos[iter][1] += delta * data->local_mat[1][0];
+ vertexCos[iter][2] += delta * data->local_mat[2][0];
+ }
+ else {
+ vertexCos[iter][0] += delta;
+ }
+ break;
+ case MOD_DISP_DIR_Y:
+ if (use_global_direction) {
+ vertexCos[iter][0] += delta * data->local_mat[0][1];
+ vertexCos[iter][1] += delta * data->local_mat[1][1];
+ vertexCos[iter][2] += delta * data->local_mat[2][1];
+ }
+ else {
+ vertexCos[iter][1] += delta;
+ }
+ break;
+ case MOD_DISP_DIR_Z:
+ if (use_global_direction) {
+ vertexCos[iter][0] += delta * data->local_mat[0][2];
+ vertexCos[iter][1] += delta * data->local_mat[1][2];
+ vertexCos[iter][2] += delta * data->local_mat[2][2];
+ }
+ else {
+ vertexCos[iter][2] += delta;
+ }
+ break;
+ case MOD_DISP_DIR_RGB_XYZ:
+ local_vec[0] = texres.tr - dmd->midlevel;
+ local_vec[1] = texres.tg - dmd->midlevel;
+ local_vec[2] = texres.tb - dmd->midlevel;
+ if (use_global_direction) {
+ mul_transposed_mat3_m4_v3(data->local_mat, local_vec);
+ }
+ mul_v3_fl(local_vec, strength);
+ add_v3_v3(vertexCos[iter], local_vec);
+ break;
+ case MOD_DISP_DIR_NOR:
+ vertexCos[iter][0] += delta * (mvert[iter].no[0] / 32767.0f);
+ vertexCos[iter][1] += delta * (mvert[iter].no[1] / 32767.0f);
+ vertexCos[iter][2] += delta * (mvert[iter].no[2] / 32767.0f);
+ break;
+ case MOD_DISP_DIR_CLNOR:
+ madd_v3_v3fl(vertexCos[iter], vert_clnors[iter], delta);
+ break;
+ }
+}
+
/* dm must be a CDDerivedMesh */
static void displaceModifier_do(
DisplaceModifierData *dmd, Object *ob,
DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
{
- int i;
MVert *mvert;
MDeformVert *dvert;
int direction = dmd->direction;
int defgrp_index;
float (*tex_co)[3];
float weight = 1.0f; /* init value unused but some compilers may complain */
- const float delta_fixed = 1.0f - dmd->midlevel; /* when no texture is used, we fallback to white */
float (*vert_clnors)[3] = NULL;
- float local_mat[4][4];
+ float local_mat[4][4] = {0};
const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL;
if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return;
@@ -259,81 +370,25 @@ static void displaceModifier_do(
copy_m4_m4(local_mat, ob->obmat);
}
- for (i = 0; i < numVerts; i++) {
- TexResult texres;
- float strength = dmd->strength;
- float delta;
- float local_vec[3];
-
- if (dvert) {
- weight = defvert_find_weight(dvert + i, defgrp_index);
- if (weight == 0.0f) continue;
- }
-
- if (dmd->texture) {
- texres.nor = NULL;
- BKE_texture_get_value(dmd->modifier.scene, dmd->texture, tex_co[i], &texres, false);
- delta = texres.tin - dmd->midlevel;
- }
- else {
- delta = delta_fixed; /* (1.0f - dmd->midlevel) */ /* never changes */
- }
+ DisplaceUserdata data = {NULL};
+ data.dmd = dmd;
+ data.dvert = dvert;
+ data.weight = weight;
+ data.defgrp_index = defgrp_index;
+ data.direction = direction;
+ data.use_global_direction = use_global_direction;
+ data.tex_co = tex_co;
+ data.vertexCos = vertexCos;
+ copy_m4_m4(data.local_mat, local_mat);
+ data.mvert = mvert;
+ data.vert_clnors = vert_clnors;
+ if (dmd->texture != NULL) {
+ data.pool = BKE_image_pool_new();
+ }
+ BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, numVerts > 512);
- if (dvert) strength *= weight;
-
- delta *= strength;
- CLAMP(delta, -10000, 10000);
-
- switch (direction) {
- case MOD_DISP_DIR_X:
- if (use_global_direction) {
- vertexCos[i][0] += delta * local_mat[0][0];
- vertexCos[i][1] += delta * local_mat[1][0];
- vertexCos[i][2] += delta * local_mat[2][0];
- }
- else {
- vertexCos[i][0] += delta;
- }
- break;
- case MOD_DISP_DIR_Y:
- if (use_global_direction) {
- vertexCos[i][0] += delta * local_mat[0][1];
- vertexCos[i][1] += delta * local_mat[1][1];
- vertexCos[i][2] += delta * local_mat[2][1];
- }
- else {
- vertexCos[i][1] += delta;
- }
- break;
- case MOD_DISP_DIR_Z:
- if (use_global_direction) {
- vertexCos[i][0] += delta * local_mat[0][2];
- vertexCos[i][1] += delta * local_mat[1][2];
- vertexCos[i][2] += delta * local_mat[2][2];
- }
- else {
- vertexCos[i][2] += delta;
- }
- break;
- case MOD_DISP_DIR_RGB_XYZ:
- local_vec[0] = texres.tr - dmd->midlevel;
- local_vec[1] = texres.tg - dmd->midlevel;
- local_vec[2] = texres.tb - dmd->midlevel;
- if (use_global_direction) {
- mul_transposed_mat3_m4_v3(local_mat, local_vec);
- }
- mul_v3_fl(local_vec, strength);
- add_v3_v3(vertexCos[i], local_vec);
- break;
- case MOD_DISP_DIR_NOR:
- vertexCos[i][0] += delta * (mvert[i].no[0] / 32767.0f);
- vertexCos[i][1] += delta * (mvert[i].no[1] / 32767.0f);
- vertexCos[i][2] += delta * (mvert[i].no[2] / 32767.0f);
- break;
- case MOD_DISP_DIR_CLNOR:
- madd_v3_v3fl(vertexCos[i], vert_clnors[i], delta);
- break;
- }
+ if (data.pool != NULL) {
+ BKE_image_pool_free(data.pool);
}
if (tex_co) {
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 38ffdaa709b..ca7b3ce8039 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -1001,8 +1001,6 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
ExplodeModifierData *emd = (ExplodeModifierData *) md;
ParticleSystemModifierData *psmd = findPrecedingParticlesystem(ob, md);
- DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
-
if (psmd) {
ParticleSystem *psys = psmd->psys;
@@ -1010,6 +1008,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (psys->part == NULL || psys->particles == NULL) return derivedData;
if (psmd->dm_final == NULL) return derivedData;
+ DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+
/* 1. find faces to be exploded if needed */
if (emd->facepa == NULL ||
psmd->flag & eParticleSystemFlag_Pars ||
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index a297dac0f55..08d00e9148a 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -235,13 +235,13 @@ struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name)
void RE_texture_rng_init() RET_NONE
void RE_texture_rng_exit() RET_NONE
-bool RE_layers_have_name(struct RenderResult *result) {STUB_ASSERT(0); return 0;}
+bool RE_layers_have_name(struct RenderResult *result) RET_ZERO
const char *RE_engine_active_view_get(struct RenderEngine *engine) RET_NULL
-void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) {STUB_ASSERT(0);}
-void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo, float *r_modelmat) {STUB_ASSERT(0);}
+void RE_engine_active_view_set(struct RenderEngine *engine, const char *viewname) RET_NONE
+void RE_engine_get_camera_model_matrix(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo, float *r_modelmat) RET_NONE
float RE_engine_get_camera_shift_x(struct RenderEngine *engine, struct Object *camera, int use_spherical_stereo) RET_ZERO
int RE_engine_get_spherical_stereo(struct RenderEngine *engine, struct Object *camera) RET_ZERO
-void RE_SetActiveRenderView(struct Render *re, const char *viewname) {STUB_ASSERT(0);}
+void RE_SetActiveRenderView(struct Render *re, const char *viewname) RET_NONE
struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int passtype, const char *viewname) RET_NULL
bool RE_HasFakeLayer(RenderResult *res) RET_ZERO
@@ -460,17 +460,17 @@ void ED_node_texture_default(const struct bContext *C, struct Tex *tex) RET_NONE
void ED_node_tag_update_id(struct ID *id) RET_NONE
void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node) RET_NONE
void ED_node_tree_update(const struct bContext *C) RET_NONE
-void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo){}
-void ED_init_custom_node_type(struct bNodeType *ntype){}
-void ED_init_custom_node_socket_type(struct bNodeSocketType *stype){}
+void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo) RET_NONE
+void ED_init_custom_node_type(struct bNodeType *ntype) RET_NONE
+void ED_init_custom_node_socket_type(struct bNodeSocketType *stype) RET_NONE
void ED_init_standard_node_socket_type(struct bNodeSocketType *stype) RET_NONE
void ED_init_node_socket_type_virtual(struct bNodeSocketType *stype) RET_NONE
-int ED_node_tree_path_length(struct SpaceNode *snode){return 0;}
-void ED_node_tree_path_get(struct SpaceNode *snode, char *value){}
-void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length){}
-void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from){}
-void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode){}
-void ED_node_tree_pop(struct SpaceNode *snode){}
+int ED_node_tree_path_length(struct SpaceNode *snode) RET_ZERO
+void ED_node_tree_path_get(struct SpaceNode *snode, char *value) RET_NONE
+void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length) RET_NONE
+void ED_node_tree_start(struct SpaceNode *snode, struct bNodeTree *ntree, struct ID *id, struct ID *from) RET_NONE
+void ED_node_tree_push(struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *gnode) RET_NONE
+void ED_node_tree_pop(struct SpaceNode *snode) RET_NONE
int ED_view3d_scene_layer_set(int lay, const int *values, int *active) RET_ZERO
void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, bool do_clip) RET_NONE
void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist) RET_NONE
@@ -668,9 +668,9 @@ struct RenderEngine *RE_engine_create(struct RenderEngineType *type) RET_NULL
void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe) RET_NONE
void RE_FreePersistentData(void) RET_NONE
void RE_point_density_cache(struct Scene *scene, struct PointDensity *pd, const bool use_render_params) RET_NONE
-void RE_point_density_minmax(struct Scene *scene, struct PointDensity *pd, const bool use_render_params, float r_min[3], float r_max[3]) RET_NONE;
-void RE_point_density_sample(struct Scene *scene, struct PointDensity *pd, int resolution, const bool use_render_params, float *values) RET_NONE;
-void RE_point_density_free(struct PointDensity *pd) RET_NONE;
+void RE_point_density_minmax(struct Scene *scene, struct PointDensity *pd, const bool use_render_params, float r_min[3], float r_max[3]) RET_NONE
+void RE_point_density_sample(struct Scene *scene, struct PointDensity *pd, int resolution, const bool use_render_params, float *values) RET_NONE
+void RE_point_density_free(struct PointDensity *pd) RET_NONE
void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index, float *age, float *lifetime, float co[3], float *size, float vel[3], float angvel[3]) RET_NONE
void RE_FreeAllPersistentData(void) RET_NONE
float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO
@@ -752,7 +752,7 @@ void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *
void macro_wrapper(struct wmOperatorType *ot, void *userdata) RET_NONE
bool pyrna_id_FromPyObject(struct PyObject *obj, struct ID **id) RET_ZERO
struct PyObject *pyrna_id_CreatePyObject(struct ID *id) RET_NULL
-void BPY_context_update(struct bContext *C) RET_NONE;
+void BPY_context_update(struct bContext *C) RET_NONE
const char *BPY_app_translations_py_pgettext(const char *msgctxt, const char *msgid) RET_ARG(msgid)
/* intern/dualcon */
diff --git a/tests/gtests/blenlib/BLI_array_store_test.cc b/tests/gtests/blenlib/BLI_array_store_test.cc
index b71dc4575f1..5af6e639e64 100644
--- a/tests/gtests/blenlib/BLI_array_store_test.cc
+++ b/tests/gtests/blenlib/BLI_array_store_test.cc
@@ -280,8 +280,8 @@ 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));
+ EXPECT_TRUE(testbuffer_list_validate(lb));
+ EXPECT_TRUE(BLI_array_store_is_valid(bs));
#ifdef DEBUG_PRINT
print_mem_saved("data", bs);
#endif
@@ -326,7 +326,7 @@ 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));
+ EXPECT_EQ(BLI_array_store_state_size_get(state), sizeof(data) - 1);
BLI_array_store_state_remove(bs, state);
BLI_array_store_destroy(bs);
}
@@ -340,7 +340,7 @@ TEST(array_store, Single)
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);
+ EXPECT_EQ(data_dst_len, sizeof(data_src));
BLI_array_store_destroy(bs);
MEM_freeN((void *)data_dst);
}
@@ -354,8 +354,8 @@ TEST(array_store, DoubleNop)
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));
+ EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), sizeof(data_src));
+ EXPECT_EQ(BLI_array_store_calc_size_expanded_get(bs), sizeof(data_src) * 2);
size_t data_dst_len;
@@ -367,7 +367,7 @@ TEST(array_store, DoubleNop)
EXPECT_STREQ(data_src, data_dst);
MEM_freeN((void *)data_dst);
- EXPECT_EQ(sizeof(data_src), data_dst_len);
+ EXPECT_EQ(data_dst_len, sizeof(data_src));
BLI_array_store_destroy(bs);
}
@@ -382,8 +382,8 @@ TEST(array_store, DoubleDiff)
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));
+ EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), sizeof(data_src_a) * 2);
+ EXPECT_EQ(BLI_array_store_calc_size_expanded_get(bs), sizeof(data_src_a) * 2);
data_dst = (char *)BLI_array_store_state_data_get_alloc(state_a, &data_dst_len);
EXPECT_STREQ(data_src_a, data_dst);
@@ -423,19 +423,19 @@ TEST(array_store, TextDupeIncreaseDecrease)
/* 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));
+ EXPECT_TRUE(testbuffer_list_validate(&lb));
+ EXPECT_TRUE(BLI_array_store_is_valid(bs));
+ EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), strlen(D));
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));
+ EXPECT_TRUE(testbuffer_list_validate(&lb));
+ EXPECT_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));
+ EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), strlen(D) * 4);
#undef D
testbuffer_list_free(&lb); \
@@ -708,7 +708,7 @@ static void random_chunk_mutate_helper(
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));
+ EXPECT_EQ(BLI_array_store_calc_size_compacted_get(bs), expected_size);
BLI_array_store_destroy(bs);
@@ -782,8 +782,8 @@ TEST(array_store, PlainTextFiles)
/* forwards */
testbuffer_list_store_populate(bs, &lb);
- EXPECT_EQ(true, testbuffer_list_validate(&lb));
- EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+ EXPECT_TRUE(testbuffer_list_validate(&lb));
+ EXPECT_TRUE(BLI_array_store_is_valid(bs));
#ifdef DEBUG_PRINT
print_mem_saved("source code forward", bs);
#endif
@@ -793,8 +793,8 @@ TEST(array_store, PlainTextFiles)
/* backwards */
testbuffer_list_store_populate(bs, &lb);
- EXPECT_EQ(true, testbuffer_list_validate(&lb));
- EXPECT_EQ(true, BLI_array_store_is_valid(bs));
+ EXPECT_TRUE(testbuffer_list_validate(&lb));
+ EXPECT_TRUE(BLI_array_store_is_valid(bs));
#ifdef DEBUG_PRINT
print_mem_saved("source code backwards", bs);
#endif
diff --git a/tests/gtests/blenlib/BLI_array_utils_test.cc b/tests/gtests/blenlib/BLI_array_utils_test.cc
index eabf5bc72cf..518cd097326 100644
--- a/tests/gtests/blenlib/BLI_array_utils_test.cc
+++ b/tests/gtests/blenlib/BLI_array_utils_test.cc
@@ -45,50 +45,50 @@ TEST(array_utils, ReverseInt4)
TEST(array_utils, FindIndexStringEmpty)
{
char data[] = "", find = '0';
- EXPECT_EQ(-1, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find));
- EXPECT_EQ(-1, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), -1);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), -1);
}
TEST(array_utils, FindIndexStringSingle)
{
char data[] = "0", find = '0';
- EXPECT_EQ(0, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find));
- EXPECT_EQ(0, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), 0);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), 0);
}
TEST(array_utils, FindIndexStringSingleMissing)
{
char data[] = "1", find = '0';
- EXPECT_EQ(-1, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find));
- EXPECT_EQ(-1, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), -1);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), -1);
}
TEST(array_utils, FindIndexString4)
{
char data[] = "0123", find = '3';
- EXPECT_EQ(3, BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find));
- EXPECT_EQ(3, BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data) - 1, &find), 3);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data) - 1, &find), 3);
}
TEST(array_utils, FindIndexInt4)
{
int data[] = {0, 1, 2, 3}, find = 3;
- EXPECT_EQ(3, BLI_array_findindex(data, ARRAY_SIZE(data), &find));
- EXPECT_EQ(3, BLI_array_rfindindex(data, ARRAY_SIZE(data), &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data), &find), 3);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data), &find), 3);
}
TEST(array_utils, FindIndexInt4_DupeEnd)
{
int data[] = {0, 1, 2, 0}, find = 0;
- EXPECT_EQ(0, BLI_array_findindex(data, ARRAY_SIZE(data), &find));
- EXPECT_EQ(3, BLI_array_rfindindex(data, ARRAY_SIZE(data), &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data), &find), 0);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data), &find), 3);
}
TEST(array_utils, FindIndexInt4_DupeMid)
{
int data[] = {1, 0, 0, 3}, find = 0;
- EXPECT_EQ(1, BLI_array_findindex(data, ARRAY_SIZE(data), &find));
- EXPECT_EQ(2, BLI_array_rfindindex(data, ARRAY_SIZE(data), &find));
+ EXPECT_EQ(BLI_array_findindex(data, ARRAY_SIZE(data), &find), 1);
+ EXPECT_EQ(BLI_array_rfindindex(data, ARRAY_SIZE(data), &find), 2);
}
TEST(array_utils, FindIndexPointer)
@@ -102,18 +102,18 @@ TEST(array_utils, FindIndexPointer)
#define STACK_PUSH_AND_CHECK_FORWARD(v, i) { \
STACK_PUSH(data, v); \
- EXPECT_EQ(i, BLI_array_findindex(data, STACK_SIZE(data), &(v))); \
+ EXPECT_EQ(BLI_array_findindex(data, STACK_SIZE(data), &(v)), i); \
} ((void)0)
#define STACK_PUSH_AND_CHECK_BACKWARD(v, i) { \
STACK_PUSH(data, v); \
- EXPECT_EQ(i, BLI_array_rfindindex(data, STACK_SIZE(data), &(v))); \
+ EXPECT_EQ(BLI_array_rfindindex(data, STACK_SIZE(data), &(v)), i); \
} ((void)0)
#define STACK_PUSH_AND_CHECK_BOTH(v, i) { \
STACK_PUSH(data, v); \
- EXPECT_EQ(i, BLI_array_findindex(data, STACK_SIZE(data), &(v))); \
- EXPECT_EQ(i, BLI_array_rfindindex(data, STACK_SIZE(data), &(v))); \
+ EXPECT_EQ(BLI_array_findindex(data, STACK_SIZE(data), &(v)), i); \
+ EXPECT_EQ(BLI_array_rfindindex(data, STACK_SIZE(data), &(v)), i); \
} ((void)0)
STACK_PUSH_AND_CHECK_BOTH(a, 0);
diff --git a/tests/gtests/blenlib/BLI_ghash_performance_test.cc b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
index fb32cb3f0a5..924c84d72d0 100644
--- a/tests/gtests/blenlib/BLI_ghash_performance_test.cc
+++ b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
@@ -118,21 +118,21 @@ static void str_ghash_tests(GHash *ghash, const char *id)
TIMEIT_START(string_lookup);
v = BLI_ghash_lookup(ghash, data_bis);
- EXPECT_EQ(data_bis[0], GET_INT_FROM_POINTER(v));
+ EXPECT_EQ(GET_INT_FROM_POINTER(v), data_bis[0]);
for (p = w = c = data_bis; *c; c++) {
if (*c == '.') {
*c = '\0';
v = BLI_ghash_lookup(ghash, w);
- EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v));
+ EXPECT_EQ(GET_INT_FROM_POINTER(v), w[0]);
v = BLI_ghash_lookup(ghash, p);
- EXPECT_EQ(p[0], GET_INT_FROM_POINTER(v));
+ EXPECT_EQ(GET_INT_FROM_POINTER(v), p[0]);
p = w = c + 1;
}
else if (*c == ' ') {
*c = '\0';
v = BLI_ghash_lookup(ghash, w);
- EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v));
+ EXPECT_EQ(GET_INT_FROM_POINTER(v), w[0]);
w = c + 1;
}
}
@@ -195,7 +195,7 @@ static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr
while (i--) {
void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(i));
- EXPECT_EQ(i, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), i);
}
TIMEIT_END(int_lookup);
@@ -214,7 +214,7 @@ static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr
TIMEIT_END(int_pop);
}
- EXPECT_EQ(0, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), 0);
BLI_ghash_free(ghash, NULL, NULL);
@@ -292,7 +292,7 @@ static void randint_ghash_tests(GHash *ghash, const char *id, const unsigned int
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));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *dt);
}
TIMEIT_END(int_lookup);
@@ -403,7 +403,7 @@ static void int4_ghash_tests(GHash *ghash, const char *id, const unsigned int nb
for (i = nbr, dt = data; i--; dt++) {
void *v = BLI_ghash_lookup(ghash, (void *)(*dt));
- EXPECT_EQ(i, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), i);
}
TIMEIT_END(int_v4_lookup);
@@ -469,7 +469,7 @@ static void multi_small_ghash_tests_one(GHash *ghash, RNG *rng, const unsigned i
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));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *dt);
}
BLI_ghash_clear(ghash, NULL, NULL);
diff --git a/tests/gtests/blenlib/BLI_ghash_test.cc b/tests/gtests/blenlib/BLI_ghash_test.cc
index ffbe5f5547f..6d075e29114 100644
--- a/tests/gtests/blenlib/BLI_ghash_test.cc
+++ b/tests/gtests/blenlib/BLI_ghash_test.cc
@@ -62,11 +62,11 @@ TEST(ghash, InsertLookup)
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
}
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE);
for (i = TESTCASE_SIZE, k = keys; i--; k++) {
void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*k));
- EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k);
}
BLI_ghash_free(ghash, NULL, NULL);
@@ -85,16 +85,16 @@ TEST(ghash, InsertRemove)
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
}
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE);
bkt_size = BLI_ghash_buckets_size(ghash);
for (i = TESTCASE_SIZE, k = keys; i--; k++) {
void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL);
- EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k);
}
- EXPECT_EQ(0, BLI_ghash_size(ghash));
- EXPECT_EQ(bkt_size, BLI_ghash_buckets_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), 0);
+ EXPECT_EQ(BLI_ghash_buckets_size(ghash), bkt_size);
BLI_ghash_free(ghash, NULL, NULL);
}
@@ -113,15 +113,15 @@ TEST(ghash, InsertRemoveShrink)
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
}
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE);
bkt_size = BLI_ghash_buckets_size(ghash);
for (i = TESTCASE_SIZE, k = keys; i--; k++) {
void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL);
- EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k);
}
- EXPECT_EQ(0, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), 0);
EXPECT_LT(BLI_ghash_buckets_size(ghash), bkt_size);
BLI_ghash_free(ghash, NULL, NULL);
@@ -141,16 +141,16 @@ TEST(ghash, Copy)
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
}
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE);
ghash_copy = BLI_ghash_copy(ghash, NULL, NULL);
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash_copy));
- EXPECT_EQ(BLI_ghash_buckets_size(ghash), BLI_ghash_buckets_size(ghash_copy));
+ EXPECT_EQ(BLI_ghash_size(ghash_copy), TESTCASE_SIZE);
+ EXPECT_EQ(BLI_ghash_buckets_size(ghash_copy), BLI_ghash_buckets_size(ghash));
for (i = TESTCASE_SIZE, k = keys; i--; k++) {
void *v = BLI_ghash_lookup(ghash_copy, SET_UINT_IN_POINTER(*k));
- EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ EXPECT_EQ(GET_UINT_FROM_POINTER(v), *k);
}
BLI_ghash_free(ghash, NULL, NULL);
@@ -171,7 +171,7 @@ TEST(ghash, Pop)
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
}
- EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), TESTCASE_SIZE);
GHashIterState pop_state = {0};
@@ -179,14 +179,14 @@ TEST(ghash, Pop)
void *k, *v;
bool success = BLI_ghash_pop(ghash, &pop_state, &k, &v);
EXPECT_EQ(k, v);
- EXPECT_EQ(success, true);
+ EXPECT_TRUE(success);
if (i % 2) {
BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(i * 4), SET_UINT_IN_POINTER(i * 4));
}
}
- EXPECT_EQ((TESTCASE_SIZE - TESTCASE_SIZE / 2 + TESTCASE_SIZE / 4), BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), (TESTCASE_SIZE - TESTCASE_SIZE / 2 + TESTCASE_SIZE / 4));
{
void *k, *v;
@@ -194,7 +194,7 @@ TEST(ghash, Pop)
EXPECT_EQ(k, v);
}
}
- EXPECT_EQ(0, BLI_ghash_size(ghash));
+ EXPECT_EQ(BLI_ghash_size(ghash), 0);
BLI_ghash_free(ghash, NULL, NULL);
}
diff --git a/tests/gtests/blenlib/BLI_hash_mm2a_test.cc b/tests/gtests/blenlib/BLI_hash_mm2a_test.cc
index b35a1a809d6..109c925af4c 100644
--- a/tests/gtests/blenlib/BLI_hash_mm2a_test.cc
+++ b/tests/gtests/blenlib/BLI_hash_mm2a_test.cc
@@ -19,9 +19,9 @@ TEST(hash_mm2a, MM2ABasic)
BLI_hash_mm2a_init(&mm2, 0);
BLI_hash_mm2a_add(&mm2, (const unsigned char *)data, strlen(data));
#ifdef __LITTLE_ENDIAN__
- EXPECT_EQ(1633988145, BLI_hash_mm2a_end(&mm2));
+ EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 1633988145);
#else
- EXPECT_EQ(959283772, BLI_hash_mm2a_end(&mm2));
+ EXPECT_EQ(BLI_hash_mm2a_end(&mm2), 959283772);
#endif
}
@@ -43,11 +43,11 @@ TEST(hash_mm2a, MM2AConcatenateStrings)
BLI_hash_mm2a_init(&mm2, 0);
BLI_hash_mm2a_add(&mm2, (const unsigned char *)data123, strlen(data123));
#ifdef __LITTLE_ENDIAN__
- EXPECT_EQ(1545105348, hash);
+ EXPECT_EQ(hash, 1545105348);
#else
- EXPECT_EQ(2604964730, hash);
+ EXPECT_EQ(hash, 2604964730);
#endif
- EXPECT_EQ(hash, BLI_hash_mm2a_end(&mm2));
+ EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash);
}
TEST(hash_mm2a, MM2AIntegers)
@@ -67,9 +67,9 @@ TEST(hash_mm2a, MM2AIntegers)
BLI_hash_mm2a_add(&mm2, (const unsigned char *)ints, sizeof(ints));
/* Yes, same hash here on little and big endian. */
#ifdef __LITTLE_ENDIAN__
- EXPECT_EQ(405493096, hash);
+ EXPECT_EQ(hash, 405493096);
#else
- EXPECT_EQ(405493096, hash);
+ EXPECT_EQ(hash, 405493096);
#endif
- EXPECT_EQ(hash, BLI_hash_mm2a_end(&mm2));
+ EXPECT_EQ(BLI_hash_mm2a_end(&mm2), hash);
}
diff --git a/tests/gtests/blenlib/BLI_listbase_test.cc b/tests/gtests/blenlib/BLI_listbase_test.cc
index 994b8f74541..4dac2d05bd8 100644
--- a/tests/gtests/blenlib/BLI_listbase_test.cc
+++ b/tests/gtests/blenlib/BLI_listbase_test.cc
@@ -74,25 +74,25 @@ TEST(listbase, FindLinkOrIndex)
/* Empty list */
BLI_listbase_clear(&lb);
- EXPECT_EQ(NULL, BLI_findlink(&lb, -1));
- EXPECT_EQ(NULL, BLI_findlink(&lb, 0));
- EXPECT_EQ(NULL, BLI_findlink(&lb, 1));
- EXPECT_EQ(NULL, BLI_rfindlink(&lb, -1));
- EXPECT_EQ(NULL, BLI_rfindlink(&lb, 0));
- EXPECT_EQ(NULL, BLI_rfindlink(&lb, 1));
- EXPECT_EQ(-1, BLI_findindex(&lb, link1));
+ EXPECT_EQ(BLI_findlink(&lb, -1), (void*)NULL);
+ EXPECT_EQ(BLI_findlink(&lb, 0), (void*)NULL);
+ EXPECT_EQ(BLI_findlink(&lb, 1), (void*)NULL);
+ EXPECT_EQ(BLI_rfindlink(&lb, -1), (void*)NULL);
+ EXPECT_EQ(BLI_rfindlink(&lb, 0), (void*)NULL);
+ EXPECT_EQ(BLI_rfindlink(&lb, 1), (void*)NULL);
+ EXPECT_EQ(BLI_findindex(&lb, link1), -1);
/* One link */
BLI_addtail(&lb, link1);
- EXPECT_EQ(link1, BLI_findlink(&lb, 0));
- EXPECT_EQ(link1, BLI_rfindlink(&lb, 0));
- EXPECT_EQ(0, BLI_findindex(&lb, link1));
+ EXPECT_EQ(BLI_findlink(&lb, 0), link1);
+ EXPECT_EQ(BLI_rfindlink(&lb, 0), link1);
+ EXPECT_EQ(BLI_findindex(&lb, link1), 0);
/* Two links */
BLI_addtail(&lb, link2);
- EXPECT_EQ(link2, BLI_findlink(&lb, 1));
- EXPECT_EQ(link2, BLI_rfindlink(&lb, 0));
- EXPECT_EQ(1, BLI_findindex(&lb, link2));
+ EXPECT_EQ(BLI_findlink(&lb, 1), link2);
+ EXPECT_EQ(BLI_rfindlink(&lb, 0), link2);
+ EXPECT_EQ(BLI_findindex(&lb, link2), 1);
BLI_freelistN(&lb);
}
diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc
index c80987c3586..d017ab18b4d 100644
--- a/tests/gtests/blenlib/BLI_path_util_test.cc
+++ b/tests/gtests/blenlib/BLI_path_util_test.cc
@@ -121,42 +121,42 @@ TEST(path_util, PathUtilFrame)
{
char path[FILE_MAX] = "";
ret = BLI_path_frame(path, 123, 1);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("123", path);
}
{
char path[FILE_MAX] = "";
ret = BLI_path_frame(path, 123, 12);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("000000000123", path);
}
{
char path[FILE_MAX] = "test_";
ret = BLI_path_frame(path, 123, 1);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("test_123", path);
}
{
char path[FILE_MAX] = "test_";
ret = BLI_path_frame(path, 1, 12);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("test_000000000001", path);
}
{
char path[FILE_MAX] = "test_############";
ret = BLI_path_frame(path, 1, 0);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("test_000000000001", path);
}
{
char path[FILE_MAX] = "test_#_#_middle";
ret = BLI_path_frame(path, 123, 0);
- EXPECT_EQ(1, ret);
+ EXPECT_EQ(ret, 1);
EXPECT_STREQ("test_#_123_middle", path);
}
@@ -164,14 +164,14 @@ TEST(path_util, PathUtilFrame)
{
char path[FILE_MAX] = "";
ret = BLI_path_frame(path, 123, 0);
- EXPECT_EQ(0, ret);
+ EXPECT_EQ(ret, 0);
EXPECT_STREQ("", path);
}
{
char path[FILE_MAX] = "test_middle";
ret = BLI_path_frame(path, 123, 0);
- EXPECT_EQ(0, ret);
+ EXPECT_EQ(ret, 0);
EXPECT_STREQ("test_middle", path);
}
}
diff --git a/tests/gtests/blenlib/BLI_polyfill2d_test.cc b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
index a4ed70fbec9..5d112751fa0 100644
--- a/tests/gtests/blenlib/BLI_polyfill2d_test.cc
+++ b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
@@ -98,14 +98,14 @@ static void test_polyfill_topology(
}
}
}
- EXPECT_EQ(poly_tot + (poly_tot - 3), BLI_edgehash_size(edgehash));
+ EXPECT_EQ(BLI_edgehash_size(edgehash), poly_tot + (poly_tot - 3));
for (i = 0; i < poly_tot; i++) {
const unsigned int v1 = i;
const unsigned int v2 = (i + 1) % poly_tot;
void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
- EXPECT_EQ(1, (void *)p != NULL);
- EXPECT_EQ(1, (intptr_t)*p);
+ EXPECT_EQ((void *)p != NULL, 1);
+ EXPECT_EQ((intptr_t)*p, 1);
}
for (ehi = BLI_edgehashIterator_new(edgehash), i = 0;
@@ -113,7 +113,7 @@ static void test_polyfill_topology(
BLI_edgehashIterator_step(ehi), i++)
{
void **p = BLI_edgehashIterator_getValue_p(ehi);
- EXPECT_EQ(true, ELEM((intptr_t)*p, 1, 2));
+ EXPECT_TRUE(ELEM((intptr_t)*p, 1, 2));
}
BLI_edgehashIterator_free(ehi);
@@ -135,7 +135,7 @@ static void test_polyfill_winding(
count[winding_test < 0.0f] += 1;
}
}
- EXPECT_EQ(true, ELEM(0, count[0], count[1]));
+ EXPECT_TRUE(ELEM(0, count[0], count[1]));
}
/**
diff --git a/tests/gtests/blenlib/BLI_stack_test.cc b/tests/gtests/blenlib/BLI_stack_test.cc
index 4c0b95f4b6b..18188937355 100644
--- a/tests/gtests/blenlib/BLI_stack_test.cc
+++ b/tests/gtests/blenlib/BLI_stack_test.cc
@@ -24,7 +24,7 @@ TEST(stack, Empty)
BLI_Stack *stack;
stack = BLI_stack_new(sizeof(int), __func__);
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
EXPECT_EQ(BLI_stack_count(stack), 0);
BLI_stack_free(stack);
}
@@ -37,11 +37,11 @@ TEST(stack, One)
stack = BLI_stack_new(sizeof(in), __func__);
BLI_stack_push(stack, (void *)&in);
- EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ EXPECT_FALSE(BLI_stack_is_empty(stack));
EXPECT_EQ(BLI_stack_count(stack), 1);
BLI_stack_pop(stack, (void *)&out);
- EXPECT_EQ(in, out);
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_EQ(out, in);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
EXPECT_EQ(BLI_stack_count(stack), 0);
BLI_stack_free(stack);
}
@@ -59,12 +59,12 @@ TEST(stack, Range)
}
for (in = tot - 1; in >= 0; in--) {
- EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ EXPECT_FALSE(BLI_stack_is_empty(stack));
BLI_stack_pop(stack, (void *)&out);
- EXPECT_EQ(in, out);
+ EXPECT_EQ(out, in);
}
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
BLI_stack_free(stack);
}
@@ -86,12 +86,12 @@ TEST(stack, String)
}
for (i = tot - 1; i >= 0; i--) {
- EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ EXPECT_FALSE(BLI_stack_is_empty(stack));
*((int *)in) = i;
BLI_stack_pop(stack, (void *)&out);
EXPECT_STREQ(in, out);
}
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
BLI_stack_free(stack);
}
@@ -115,7 +115,7 @@ TEST(stack, Peek)
EXPECT_EQ(*ret, in[i % ARRAY_SIZE(in)]);
}
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
BLI_stack_free(stack);
}
@@ -140,7 +140,7 @@ TEST(stack, Clear)
}
BLI_stack_clear(stack);
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
/* and again, this time check its valid */
for (in = 0; in < tot; in++) {
@@ -148,12 +148,12 @@ TEST(stack, Clear)
}
for (in = tot - 1; in >= 0; in--) {
- EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ EXPECT_FALSE(BLI_stack_is_empty(stack));
BLI_stack_pop(stack, (void *)&out);
- EXPECT_EQ(in, out);
+ EXPECT_EQ(out, in);
}
- EXPECT_EQ(BLI_stack_is_empty(stack), true);
+ EXPECT_TRUE(BLI_stack_is_empty(stack));
/* without this, we wont test case when mixed free/used */
tot /= 2;
@@ -204,10 +204,10 @@ TEST(stack, Reuse)
while (!BLI_stack_is_empty(stack)) {
i--;
BLI_stack_pop(stack, (void *)&sizes_test[i]);
- EXPECT_EQ(sizes[i], sizes_test[i]);
+ EXPECT_EQ(sizes_test[i], sizes[i]);
EXPECT_GT(i, -1);
}
- EXPECT_EQ(i, 0);
+ EXPECT_EQ(0, i);
EXPECT_EQ(memcmp(sizes, sizes_test, sizeof(sizes) - sizeof(int)), 0);
diff --git a/tests/gtests/blenlib/BLI_string_test.cc b/tests/gtests/blenlib/BLI_string_test.cc
index 08f2a745bdb..f6f7e17c8ca 100644
--- a/tests/gtests/blenlib/BLI_string_test.cc
+++ b/tests/gtests/blenlib/BLI_string_test.cc
@@ -44,7 +44,7 @@ TEST(string, StrPartition)
/* "mat.e-r_ial" -> "mat", '.', "e-r_ial", 3 */
pre_ln = BLI_str_partition(str, delim, &sep, &suf);
- EXPECT_EQ(3, pre_ln);
+ EXPECT_EQ(pre_ln, 3);
EXPECT_EQ(&str[3], sep);
EXPECT_STREQ("e-r_ial", suf);
}
@@ -55,7 +55,7 @@ TEST(string, StrPartition)
/* ".mate-rial--" -> "", '.', "mate-rial--", 0 */
pre_ln = BLI_str_partition(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
+ EXPECT_EQ(pre_ln, 0);
EXPECT_EQ(&str[0], sep);
EXPECT_STREQ("mate-rial--", suf);
}
@@ -65,7 +65,7 @@ TEST(string, StrPartition)
/* ".__.--_" -> "", '.', "__.--_", 0 */
pre_ln = BLI_str_partition(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
+ EXPECT_EQ(pre_ln, 0);
EXPECT_EQ(&str[0], sep);
EXPECT_STREQ("__.--_", suf);
}
@@ -75,9 +75,9 @@ TEST(string, StrPartition)
/* "" -> "", NULL, NULL, 0 */
pre_ln = BLI_str_partition(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 0);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
{
@@ -85,9 +85,9 @@ TEST(string, StrPartition)
/* "material" -> "material", NULL, NULL, 8 */
pre_ln = BLI_str_partition(str, delim, &sep, &suf);
- EXPECT_EQ(8, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 8);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -103,7 +103,7 @@ TEST(string, StrRPartition)
/* "mat.e-r_ial" -> "mat.e-r", '_', "ial", 7 */
pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
- EXPECT_EQ(7, pre_ln);
+ EXPECT_EQ(pre_ln, 7);
EXPECT_EQ(&str[7], sep);
EXPECT_STREQ("ial", suf);
}
@@ -114,7 +114,7 @@ TEST(string, StrRPartition)
/* ".mate-rial--" -> ".mate-rial-", '-', "", 11 */
pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
- EXPECT_EQ(11, pre_ln);
+ EXPECT_EQ(pre_ln, 11);
EXPECT_EQ(&str[11], sep);
EXPECT_STREQ("", suf);
}
@@ -124,7 +124,7 @@ TEST(string, StrRPartition)
/* ".__.--_" -> ".__.--", '_', "", 6 */
pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
- EXPECT_EQ(6, pre_ln);
+ EXPECT_EQ(pre_ln, 6);
EXPECT_EQ(&str[6], sep);
EXPECT_STREQ("", suf);
}
@@ -134,9 +134,9 @@ TEST(string, StrRPartition)
/* "" -> "", NULL, NULL, 0 */
pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 0);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
{
@@ -144,9 +144,9 @@ TEST(string, StrRPartition)
/* "material" -> "material", NULL, NULL, 8 */
pre_ln = BLI_str_rpartition(str, delim, &sep, &suf);
- EXPECT_EQ(8, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 8);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -164,7 +164,7 @@ TEST(string, StrPartitionEx)
/* "mat.e-r_ia.l" over "mat.e-r" -> "mat.e", '.', "r_ia.l", 3 */
pre_ln = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true);
- EXPECT_EQ(5, pre_ln);
+ EXPECT_EQ(pre_ln, 5);
EXPECT_EQ(&str[5], sep);
EXPECT_STREQ("r_ia.l", suf);
}
@@ -175,9 +175,9 @@ TEST(string, StrPartitionEx)
/* "mate.rial" over "mate" -> "mate.rial", NULL, NULL, 4 */
pre_ln = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true);
- EXPECT_EQ(4, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 4);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -193,7 +193,7 @@ TEST(string, StrPartitionUtf8)
/* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */
pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(2, pre_ln);
+ EXPECT_EQ(pre_ln, 2);
EXPECT_EQ(&str[2], sep);
EXPECT_STREQ("te-r\xe2\x98\xafial", suf);
}
@@ -204,7 +204,7 @@ TEST(string, StrPartitionUtf8)
/* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "", '\xe2\x98\xaf', "mate-rial-\xc3\xb1", 0 */
pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
+ EXPECT_EQ(pre_ln, 0);
EXPECT_EQ(&str[0], sep);
EXPECT_STREQ("mate-rial-\xc3\xb1", suf);
}
@@ -214,7 +214,7 @@ TEST(string, StrPartitionUtf8)
/* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "", '\xe2\x98\xaf', ".\xc3\xb1_.--\xc3\xb1", 0 */
pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
+ EXPECT_EQ(pre_ln, 0);
EXPECT_EQ(&str[0], sep);
EXPECT_STREQ(".\xc3\xb1_.--\xc3\xb1", suf);
}
@@ -224,9 +224,9 @@ TEST(string, StrPartitionUtf8)
/* "" -> "", NULL, NULL, 0 */
pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 0);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
{
@@ -234,9 +234,9 @@ TEST(string, StrPartitionUtf8)
/* "material" -> "material", NULL, NULL, 8 */
pre_ln = BLI_str_partition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(8, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 8);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -252,7 +252,7 @@ TEST(string, StrRPartitionUtf8)
/* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "mat\xc3\xb1te-r", '\xe2\x98\xaf', "ial", 8 */
pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(8, pre_ln);
+ EXPECT_EQ(pre_ln, 8);
EXPECT_EQ(&str[8], sep);
EXPECT_STREQ("ial", suf);
}
@@ -263,7 +263,7 @@ TEST(string, StrRPartitionUtf8)
/* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "\xe2\x98\xafmate-rial-", '\xc3\xb1', "", 13 */
pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(13, pre_ln);
+ EXPECT_EQ(pre_ln, 13);
EXPECT_EQ(&str[13], sep);
EXPECT_STREQ("", suf);
}
@@ -273,7 +273,7 @@ TEST(string, StrRPartitionUtf8)
/* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "\xe2\x98\xaf.\xc3\xb1_.--", '\xc3\xb1', "", 10 */
pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(10, pre_ln);
+ EXPECT_EQ(pre_ln, 10);
EXPECT_EQ(&str[10], sep);
EXPECT_STREQ("", suf);
}
@@ -283,9 +283,9 @@ TEST(string, StrRPartitionUtf8)
/* "" -> "", NULL, NULL, 0 */
pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(0, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 0);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
{
@@ -293,9 +293,9 @@ TEST(string, StrRPartitionUtf8)
/* "material" -> "material", NULL, NULL, 8 */
pre_ln = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
- EXPECT_EQ(8, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 8);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -313,7 +313,7 @@ TEST(string, StrPartitionExUtf8)
/* "ma\xc3\xb1te-r\xe2\x98\xafial" over "ma\xc3\xb1te" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */
pre_ln = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true);
- EXPECT_EQ(2, pre_ln);
+ EXPECT_EQ(pre_ln, 2);
EXPECT_EQ(&str[2], sep);
EXPECT_STREQ("te-r\xe2\x98\xafial", suf);
}
@@ -324,9 +324,9 @@ TEST(string, StrPartitionExUtf8)
/* "mate\xe2\x98\xafrial" over "mate" -> "mate\xe2\x98\xafrial", NULL, NULL, 4 */
pre_ln = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true);
- EXPECT_EQ(4, pre_ln);
- EXPECT_EQ(NULL, sep);
- EXPECT_EQ(NULL, suf);
+ EXPECT_EQ(pre_ln, 4);
+ EXPECT_EQ(sep, (void*)NULL);
+ EXPECT_EQ(suf, (void*)NULL);
}
}
@@ -373,7 +373,7 @@ TEST(string, StrFormatIntGrouped)
const int word_cmp_size = ARRAY_SIZE(word_cmp); \
const int word_num = BLI_string_find_split_words( \
word_str_src, word_str_src_len, ' ', word_info, word_cmp_size_input); \
- EXPECT_EQ(word_num, word_cmp_size - 1); \
+ EXPECT_EQ(word_cmp_size - 1, word_num); \
EXPECT_EQ_ARRAY_ND<const int[2]>(word_cmp, word_info, word_cmp_size, 2); \
} ((void)0)
@@ -449,20 +449,20 @@ TEST(string, StringStrncasestr)
const char *res;
res = BLI_strncasestr(str_test0, "", 0);
- EXPECT_EQ(str_test0, res);
+ EXPECT_EQ(res, str_test0);
res = BLI_strncasestr(str_test0, " ", 1);
- EXPECT_EQ(str_test0 + 6, res);
+ EXPECT_EQ(res, str_test0 + 6);
res = BLI_strncasestr(str_test0, "her", 3);
- EXPECT_EQ(str_test0 + 7, res);
+ EXPECT_EQ(res, str_test0 + 7);
res = BLI_strncasestr(str_test0, "ARCh", 4);
- EXPECT_EQ(str_test0 + 2, res);
+ EXPECT_EQ(res, str_test0 + 2);
res = BLI_strncasestr(str_test0, "earcq", 4);
- EXPECT_EQ(str_test0 + 1, res);
+ EXPECT_EQ(res, str_test0 + 1);
res = BLI_strncasestr(str_test0, "not there", 9);
- EXPECT_EQ(NULL, res);
+ EXPECT_EQ(res, (void*)NULL);
}
diff --git a/tests/gtests/blenlib/BLI_string_utf8_test.cc b/tests/gtests/blenlib/BLI_string_utf8_test.cc
index c0beb92eeec..95d73b4242f 100644
--- a/tests/gtests/blenlib/BLI_string_utf8_test.cc
+++ b/tests/gtests/blenlib/BLI_string_utf8_test.cc
@@ -298,7 +298,7 @@ TEST(string, Utf8InvalidBytes)
const int num_errors_found = BLI_utf8_invalid_strip(buff, sizeof(buff) - 1);
printf("[%02d] -> [%02d] \"%s\" -> \"%s\"\n", num_errors, num_errors_found, tst, buff);
- EXPECT_EQ(num_errors, num_errors_found);
+ EXPECT_EQ(num_errors_found, num_errors);
EXPECT_STREQ(buff, tst_stripped);
}
}
diff --git a/tests/gtests/bmesh/bmesh_core_test.cc b/tests/gtests/bmesh/bmesh_core_test.cc
index f386abc0b2b..b2cb1a4e8a3 100644
--- a/tests/gtests/bmesh/bmesh_core_test.cc
+++ b/tests/gtests/bmesh/bmesh_core_test.cc
@@ -12,18 +12,18 @@ TEST(bmesh_core, BMVertCreate) {
BMeshCreateParams bm_params;
bm_params.use_toolflags = true;
bm = BM_mesh_create(&bm_mesh_allocsize_default, &bm_params);
- EXPECT_EQ(0, bm->totvert);
+ EXPECT_EQ(bm->totvert, 0);
/* make a custom layer so we can see if it is copied properly */
BM_data_layer_add(bm, &bm->vdata, CD_PROP_FLT);
bv1 = BM_vert_create(bm, co1, NULL, BM_CREATE_NOP);
ASSERT_TRUE(bv1 != NULL);
- EXPECT_EQ(1.0f, bv1->co[0]);
- EXPECT_EQ(2.0f, bv1->co[1]);
- EXPECT_EQ(0.0f, bv1->co[2]);
+ EXPECT_EQ(bv1->co[0], 1.0f);
+ EXPECT_EQ(bv1->co[1], 2.0f);
+ EXPECT_EQ(bv1->co[2], 0.0f);
EXPECT_TRUE(is_zero_v3(bv1->no));
- EXPECT_EQ((char)BM_VERT, bv1->head.htype);
- EXPECT_EQ(0, bv1->head.hflag);
- EXPECT_EQ(0, bv1->head.api_flag);
+ EXPECT_EQ(bv1->head.htype, (char)BM_VERT);
+ EXPECT_EQ(bv1->head.hflag, 0);
+ EXPECT_EQ(bv1->head.api_flag, 0);
bv2 = BM_vert_create(bm, NULL, NULL, BM_CREATE_NOP);
ASSERT_TRUE(bv2 != NULL);
EXPECT_TRUE(is_zero_v3(bv2->co));
@@ -33,7 +33,7 @@ TEST(bmesh_core, BMVertCreate) {
bv3 = BM_vert_create(bm, co1, bv2, BM_CREATE_NOP);
ASSERT_TRUE(bv3 != NULL);
EXPECT_FALSE(BM_elem_flag_test((BMElem *)bv3, BM_ELEM_SELECT));
- EXPECT_EQ(1.5f, BM_elem_float_data_get(&bm->vdata, bv3, CD_PROP_FLT));
- EXPECT_EQ(3, BM_mesh_elem_count(bm, BM_VERT));
+ EXPECT_EQ(BM_elem_float_data_get(&bm->vdata, bv3, CD_PROP_FLT), 1.5f);
+ EXPECT_EQ(BM_mesh_elem_count(bm, BM_VERT), 3);
BM_mesh_free(bm);
}
diff --git a/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc b/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc
index 345c3824b63..01ff38f0528 100644
--- a/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc
+++ b/tests/gtests/guardedalloc/guardedalloc_alignment_test.cc
@@ -8,7 +8,7 @@ extern "C" {
#include "MEM_guardedalloc.h"
-#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ(0, (size_t)ptr % align)
+#define CHECK_ALIGNMENT(ptr, align) EXPECT_EQ((size_t)ptr % align, 0)
namespace {
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index 4b5666e9b5a..b76c47fcf25 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -95,6 +95,11 @@ add_test(bevel ${TEST_BLENDER_EXE}
--python-text run_tests
)
+add_test(split_faces ${TEST_BLENDER_EXE}
+ ${TEST_SRC_DIR}/modeling/split_faces_test.blend
+ --python-text run_tests
+)
+
# ------------------------------------------------------------------------------
# IO TESTS
@@ -417,7 +422,12 @@ if(WITH_CYCLES)
-idiff "${OPENIMAGEIO_IDIFF}"
)
endif()
- endmacro()
+ endmacro()
+ if(WITH_OPENGL_TESTS)
+ add_cycles_render_test(opengl)
+ endif()
+ add_cycles_render_test(image)
+ add_cycles_render_test(mblur)
add_cycles_render_test(reports)
add_cycles_render_test(render)
add_cycles_render_test(shader)
diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py
index 64a71da301a..a030cc5e0de 100755
--- a/tests/python/cycles_render_tests.py
+++ b/tests/python/cycles_render_tests.py
@@ -47,20 +47,41 @@ def printMessage(type, status, message):
def render_file(filepath):
- command = (
- BLENDER,
- "--background",
- "-noaudio",
- "--factory-startup",
- "--enable-autoexec",
- filepath,
- "-E", "CYCLES",
- # Run with OSL enabled
- # "--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True",
- "-o", TEMP_FILE_MASK,
- "-F", "PNG",
- "-f", "1",
+ dirname = os.path.dirname(filepath)
+ basedir = os.path.dirname(dirname)
+ subject = os.path.basename(dirname)
+ if subject == 'opengl':
+ command = (
+ BLENDER,
+ "--window-geometry", "0", "0", "1", "1",
+ "-noaudio",
+ "--factory-startup",
+ "--enable-autoexec",
+ filepath,
+ "-E", "CYCLES",
+ # Run with OSL enabled
+ # "--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True",
+ "-o", TEMP_FILE_MASK,
+ "-F", "PNG",
+ '--python', os.path.join(basedir,
+ "util",
+ "render_opengl.py")
)
+ else:
+ command = (
+ BLENDER,
+ "--background",
+ "-noaudio",
+ "--factory-startup",
+ "--enable-autoexec",
+ filepath,
+ "-E", "CYCLES",
+ # Run with OSL enabled
+ # "--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True",
+ "-o", TEMP_FILE_MASK,
+ "-F", "PNG",
+ "-f", "1",
+ )
try:
output = subprocess.check_output(command)
if VERBOSE: