From 887fc0ff6d1ed645b8f66bdc8e2212dc253cc7b9 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Tue, 31 Jan 2017 11:00:18 +0100 Subject: [PATCH 01/18] Silence unused var warnings after rBac58a7fa --- source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp index b8971fffe3e..36bc176b1a6 100644 --- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp +++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp @@ -43,8 +43,6 @@ void HueSaturationValueNode::convertToOperations(NodeConverter &converter, const NodeInput *valueSocket = this->getInputSocket(3); NodeInput *facSocket = this->getInputSocket(4); NodeOutput *outputSocket = this->getOutputSocket(0); - bNode *editorsnode = getbNode(); - NodeHueSat *storage = (NodeHueSat *)editorsnode->storage; ConvertRGBToHSVOperation *rgbToHSV = new ConvertRGBToHSVOperation(); converter.addOperation(rgbToHSV); From b3690cdecde587119944b88da0259ec96d6fe1ec Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Jan 2017 11:55:29 +0100 Subject: [PATCH 02/18] Fix variable shadow and avoid calculating same value twice --- .../blender/editors/transform/transform_snap_object.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index bed451a32d8..d1bcec39611 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1117,12 +1117,13 @@ static bool snapDerivedMesh( float depth_range_local[2]; if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - copy_v3_v3(ray_org_local, snapdata->ray_origin); - mul_m4_v3(imat, ray_org_local); depth_range_local[0] = snapdata->depth_range[0] * local_scale; depth_range_local[1] = local_depth + depth_range_local[0]; } + copy_v3_v3(ray_org_local, snapdata->ray_origin); + mul_m4_v3(imat, ray_org_local); + if (do_bb) { BoundBox *bb = BKE_object_boundbox_get(ob); @@ -1246,11 +1247,6 @@ static bool snapDerivedMesh( * 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. */ From 326516c9d74b599b8bfbd6960843a522a89594f8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Jan 2017 12:08:19 +0100 Subject: [PATCH 03/18] Cycles: Fix spelling in comment --- intern/cycles/blender/addon/engine.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 2c5365c9189..c8c9ef58c52 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -62,7 +62,7 @@ def _parse_command_line(): num_resumable_chunks = None current_resumable_chunk = None - # TODO(sergey): Add some nice error ptins if argument is not used properly. + # TODO(sergey): Add some nice error prints if argument is not used properly. idx = 0 while idx < len(argv) - 1: arg = argv[idx] From a90622ce935acfe769e3100c83a8bb1f5c0ecaec Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 31 Jan 2017 12:17:42 +0100 Subject: [PATCH 04/18] Fix T50331: New Dependency Graph - "frame" python driver expression not working --- .../blender/depsgraph/intern/builder/deg_builder_relations.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index ba7818c21ad..94cff521edc 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -129,8 +129,8 @@ static bool python_driver_depends_on_time(ChannelDriver *driver) /* Function calls are considered dependent on a time. */ return true; } - if (strstr(driver->expression, "time") != NULL) { - /* Variable `time` depends on time. */ + if (strstr(driver->expression, "frame") != NULL) { + /* Variable `frame` depends on time. */ /* TODO(sergey): This is a bit weak, but not sure about better way of * handling this. */ From 75a4c836d60126aaa899c1ac79cb3ad38c5aaa7a Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 31 Jan 2017 17:10:34 -0300 Subject: [PATCH 05/18] Snap System: Invert the test order of the elements to snap (useful for ruler) When the function that tests snap on multiple elements starts from the face and ends at the vertex, the transition between elements becomes much smoother. --- .../editors/transform/transform_snap_object.c | 85 +++++++++++-------- 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index d1bcec39611..5e4aea63bb6 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -387,7 +387,7 @@ typedef struct Nearest2dPrecalc { float ray_direction_local[3]; float ray_inv_dir[3]; - float depth_range[2]; + float ray_min_dist; float pmat[4][4]; /* perspective matrix multiplied by object matrix */ float win_half[2]; @@ -401,12 +401,12 @@ typedef struct Nearest2dPrecalc { static void dist_squared_to_projected_aabb_precalc( struct Nearest2dPrecalc *neasrest_precalc, float lpmat[4][4], const float win_half[2], - const float depth_range[2], const float mval[2], + const float ray_min_dist, const float mval[2], const float ray_origin_local[3], const float ray_direction_local[3]) { copy_m4_m4(neasrest_precalc->pmat, lpmat); copy_v2_v2(neasrest_precalc->win_half, win_half); - copy_v2_v2(neasrest_precalc->depth_range, depth_range); + neasrest_precalc->ray_min_dist = ray_min_dist; copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local); copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local); @@ -513,11 +513,11 @@ static float dist_squared_to_projected_aabb( #define IGNORE_BEHIND_RAY #ifdef IGNORE_BEHIND_RAY /* `if rtmax < depth_min`, the hit is behind us */ - if (rtmax < data->depth_range[0]) { + if (rtmax < data->ray_min_dist) { /* Test if the entire AABB is behind us */ float depth = depth_get( local_bvmax, data->ray_origin_local, data->ray_direction_local); - if (depth < (data->depth_range[0])) { + if (depth < (data->ray_min_dist)) { return FLT_MAX; } } @@ -528,11 +528,11 @@ static float dist_squared_to_projected_aabb( } #ifdef IGNORE_BEHIND_RAY /* `if rtmin < depth_min`, the hit is behing us */ - else if (rtmin < data->depth_range[0]) { + else if (rtmin < data->ray_min_dist) { /* Test if the entire AABB is behind us */ float depth = depth_get( local_bvmax, data->ray_origin_local, data->ray_direction_local); - if (depth < (data->depth_range[0])) { + if (depth < (data->ray_min_dist)) { return FLT_MAX; } } @@ -606,13 +606,13 @@ static float dist_squared_to_projected_aabb( static float dist_squared_to_projected_aabb_simple( float lpmat[4][4], const float win_half[2], - const float depth_range[2], const float mval[2], + const float ray_min_dist, const float mval[2], const float ray_origin_local[3], const float ray_direction_local[3], const float bbmin[3], const float bbmax[3]) { struct Nearest2dPrecalc data; dist_squared_to_projected_aabb_precalc( - &data, lpmat, win_half, depth_range, + &data, lpmat, win_half, ray_min_dist, mval, ray_origin_local, ray_direction_local); bool dummy[3] = {true, true, true}; @@ -646,6 +646,7 @@ typedef struct Nearest2dUserData { bool r_axis_closest[3]; + float depth_range[2]; void *userdata; int index; float co[3]; @@ -674,7 +675,7 @@ static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, vo }; if (test_projected_vert_dist( - neasrest_precalc->depth_range, + data->depth_range, neasrest_precalc->mval, co, neasrest_precalc->pmat, neasrest_precalc->win_half, @@ -697,7 +698,7 @@ static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int i get_edge_verts(data->userdata, index, v_pair); if (test_projected_edge_dist( - neasrest_precalc->depth_range, + data->depth_range, neasrest_precalc->mval, neasrest_precalc->pmat, neasrest_precalc->win_half, @@ -1114,11 +1115,10 @@ static bool snapDerivedMesh( float lpmat[4][4]; float ray_org_local[3]; - float depth_range_local[2]; + float ray_min_dist; if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) { mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - depth_range_local[0] = snapdata->depth_range[0] * local_scale; - depth_range_local[1] = local_depth + depth_range_local[0]; + ray_min_dist = snapdata->depth_range[0] * local_scale; } copy_v3_v3(ray_org_local, snapdata->ray_origin); @@ -1137,7 +1137,7 @@ static bool snapDerivedMesh( /* 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, snapdata->depth_range, snapdata->mval, + 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)) { @@ -1320,12 +1320,13 @@ static bool snapDerivedMesh( .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, .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->win_half, - depth_range_local, snapdata->mval, ray_org_local, ray_normal_local); + ray_min_dist, snapdata->mval, ray_org_local, ray_normal_local); BVHTree_WalkLeafCallback cb_walk_leaf = (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) ? @@ -1611,16 +1612,16 @@ static bool snapEditMesh( .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, .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], depth_range_local[2]; + float lpmat[4][4]; mul_m4_m4m4(lpmat, snapdata->pmat, obmat); - depth_range_local[0] = snapdata->depth_range[0] * local_scale; - depth_range_local[1] = local_depth + depth_range_local[0]; dist_squared_to_projected_aabb_precalc( &neasrest2d.data_precalc, lpmat, snapdata->win_half, - snapdata->depth_range, snapdata->mval, ray_org_local, ray_normal_local); + (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) ? @@ -2076,23 +2077,37 @@ static bool transform_snap_context_project_view3d_mixed_impl( BLI_assert(snap_to_flag != 0); BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0); - for (int i = 0; i < 3; i++) { - if ((snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) { - - if (ED_transform_snap_object_project_view3d( - sctx, - elem_type[i], params, - mval, dist_px, &ray_depth, - r_co, r_no)) - { - is_hit = true; - if (use_depth == false) { - ray_depth = BVH_RAYCAST_DIST_MAX; - } - else { + if (use_depth) { + const float dist_px_orig = *dist_px; + for (int i = 2; i >= 0; i--) { + if (snap_to_flag & (1 << i)) { + if (i == 0) + *dist_px = dist_px_orig; + if (ED_transform_snap_object_project_view3d( + sctx, + elem_type[i], params, + mval, dist_px, &ray_depth, + r_co, r_no)) + { /* 0.01 is a random but small value to prioritizing * the first elements of the loop */ - ray_depth -= 0.01f; + ray_depth += 0.01f; + is_hit = true; + } + } + } + } + else { + for (int i = 0; i < 3; i++) { + if (snap_to_flag & (1 << i)) { + if (ED_transform_snap_object_project_view3d( + sctx, + elem_type[i], params, + mval, dist_px, &ray_depth, + r_co, r_no)) + { + is_hit = true; + break; } } } From 92258f3678b464894479a2939d848341394bfcd1 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 31 Jan 2017 21:43:44 -0300 Subject: [PATCH 06/18] Snap System: BVH: Ignore calculations, in parent nodes, used only in perspective view Strangely this change does not affect the performance very much. Suzanne subdividide 6x (ortho view): Before:0.00013983 After :0.00013920 But it makes it easier to read the code --- .../editors/transform/transform_snap_object.c | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 5e4aea63bb6..85209b07677 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -389,6 +389,7 @@ typedef struct Nearest2dPrecalc { float ray_min_dist; float pmat[4][4]; /* perspective matrix multiplied by object matrix */ + bool is_persp; float win_half[2]; float mval[2]; @@ -400,11 +401,12 @@ typedef struct Nearest2dPrecalc { */ static void dist_squared_to_projected_aabb_precalc( struct Nearest2dPrecalc *neasrest_precalc, - float lpmat[4][4], const float win_half[2], + float lpmat[4][4], bool is_persp, const float win_half[2], const float ray_min_dist, const float mval[2], const float ray_origin_local[3], const float ray_direction_local[3]) { copy_m4_m4(neasrest_precalc->pmat, lpmat); + neasrest_precalc->is_persp = is_persp; copy_v2_v2(neasrest_precalc->win_half, win_half); neasrest_precalc->ray_min_dist = ray_min_dist; @@ -549,20 +551,24 @@ static float dist_squared_to_projected_aabb( float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]); float (*pmat)[4] = data->pmat; - float depth_a = mul_project_m4_v3_zfac(pmat, va); - float depth_b = depth_a + pmat[main_axis][3] * scale; float va2d[2] = { (dot_m4_v3_row_x(pmat, va) + pmat[3][0]), (dot_m4_v3_row_y(pmat, va) + pmat[3][1]), }; float vb2d[2] = { - (va2d[0] + pmat[main_axis][0] * scale) / depth_b, - (va2d[1] + pmat[main_axis][1] * scale) / depth_b, + (va2d[0] + pmat[main_axis][0] * scale), + (va2d[1] + pmat[main_axis][1] * scale), }; - va2d[0] /= depth_a; - va2d[1] /= depth_a; + if (data->is_persp) { + float depth_a = mul_project_m4_v3_zfac(pmat, va); + float depth_b = depth_a + pmat[main_axis][3] * scale; + va2d[0] /= depth_a; + va2d[1] /= depth_a; + vb2d[0] /= depth_b; + vb2d[1] /= depth_b; + } va2d[0] += 1.0f; va2d[1] += 1.0f; @@ -612,7 +618,7 @@ static float dist_squared_to_projected_aabb_simple( { struct Nearest2dPrecalc data; dist_squared_to_projected_aabb_precalc( - &data, lpmat, win_half, ray_min_dist, + &data, lpmat, true, win_half, ray_min_dist, mval, ray_origin_local, ray_direction_local); bool dummy[3] = {true, true, true}; @@ -641,7 +647,6 @@ static float dist_aabb_to_plane( typedef struct Nearest2dUserData { struct Nearest2dPrecalc data_precalc; - bool is_persp; float dist_px_sq; bool r_axis_closest[3]; @@ -679,7 +684,7 @@ static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, vo neasrest_precalc->mval, co, neasrest_precalc->pmat, neasrest_precalc->win_half, - data->is_persp, + neasrest_precalc->is_persp, &data->dist_px_sq, data->co)) { @@ -702,7 +707,7 @@ static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int i neasrest_precalc->mval, neasrest_precalc->pmat, neasrest_precalc->win_half, - data->is_persp, + neasrest_precalc->is_persp, neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local, v_pair[0], v_pair[1], @@ -1317,7 +1322,6 @@ static bool snapDerivedMesh( BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH}; Nearest2dUserData neasrest2d = { - .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, .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]}, @@ -1325,7 +1329,8 @@ static bool snapDerivedMesh( .index = -1}; dist_squared_to_projected_aabb_precalc( - &neasrest2d.data_precalc, lpmat, snapdata->win_half, + &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 = @@ -1609,7 +1614,6 @@ static bool snapEditMesh( BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH}; Nearest2dUserData neasrest2d = { - .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP, .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]}, @@ -1619,7 +1623,8 @@ static bool snapEditMesh( float lpmat[4][4]; mul_m4_m4m4(lpmat, snapdata->pmat, obmat); dist_squared_to_projected_aabb_precalc( - &neasrest2d.data_precalc, lpmat, snapdata->win_half, + &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); From fa19940dc63d22cc03e1411e2add8ec8647b5f28 Mon Sep 17 00:00:00 2001 From: Lukas Stockner Date: Wed, 1 Feb 2017 05:43:17 +0100 Subject: [PATCH 07/18] Cycles: Fix rng_state initialization when using resumable rendering --- intern/cycles/blender/blender_session.cpp | 3 +++ intern/cycles/kernel/kernel_path_common.h | 2 +- intern/cycles/kernel/kernel_types.h | 3 +++ intern/cycles/render/integrator.cpp | 2 ++ intern/cycles/render/integrator.h | 1 + 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 04b5c3fa013..2f30cbd961f 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -1352,6 +1352,9 @@ void BlenderSession::update_resumable_tile_manager(int num_samples) VLOG(1) << "Samples range start is " << range_start_sample << ", " << "number of samples to render is " << range_num_samples; + scene->integrator->start_sample = range_start_sample; + scene->integrator->tag_update(scene); + session->tile_manager.range_start_sample = range_start_sample; session->tile_manager.range_num_samples = range_num_samples; } diff --git a/intern/cycles/kernel/kernel_path_common.h b/intern/cycles/kernel/kernel_path_common.h index 13597eab287..7b903556bf9 100644 --- a/intern/cycles/kernel/kernel_path_common.h +++ b/intern/cycles/kernel/kernel_path_common.h @@ -30,7 +30,7 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg, int num_samples = kernel_data.integrator.aa_samples; - if(sample == 0) { + if(sample == kernel_data.integrator.start_sample) { *rng_state = hash_int_2d(x, y); } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 4d9c4b2e6f1..8c271c75e44 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1187,6 +1187,9 @@ typedef struct KernelIntegrator { int volume_samples; float light_inv_rr_threshold; + + int start_sample; + int pad1, pad2, pad3; } KernelIntegrator; static_assert_align(KernelIntegrator, 16); diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index 41e1dae2745..1ab0f9874f2 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -64,6 +64,7 @@ NODE_DEFINE(Integrator) SOCKET_INT(mesh_light_samples, "Mesh Light Samples", 1); SOCKET_INT(subsurface_samples, "Subsurface Samples", 1); SOCKET_INT(volume_samples, "Volume Samples", 1); + SOCKET_INT(start_sample, "Start Sample", 0); SOCKET_BOOLEAN(sample_all_lights_direct, "Sample All Lights Direct", true); SOCKET_BOOLEAN(sample_all_lights_indirect, "Sample All Lights Indirect", true); @@ -161,6 +162,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene kintegrator->mesh_light_samples = mesh_light_samples; kintegrator->subsurface_samples = subsurface_samples; kintegrator->volume_samples = volume_samples; + kintegrator->start_sample = start_sample; if(method == BRANCHED_PATH) { kintegrator->sample_all_lights_direct = sample_all_lights_direct; diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index f8cc0507ada..27fff4831e5 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -66,6 +66,7 @@ public: int mesh_light_samples; int subsurface_samples; int volume_samples; + int start_sample; bool sample_all_lights_direct; bool sample_all_lights_indirect; From c231c29afae2b26157faa9e22e2e6a104ed87a22 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 1 Feb 2017 10:13:40 +0100 Subject: [PATCH 08/18] Cycles tests: Allow python auto-exec --- tests/python/cycles_render_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py index ae8848570f0..64a71da301a 100755 --- a/tests/python/cycles_render_tests.py +++ b/tests/python/cycles_render_tests.py @@ -52,6 +52,7 @@ def render_file(filepath): "--background", "-noaudio", "--factory-startup", + "--enable-autoexec", filepath, "-E", "CYCLES", # Run with OSL enabled From fb61711b1a9ef96becec8eb15916f057055f567b Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 1 Feb 2017 12:52:26 +0100 Subject: [PATCH 09/18] Fix T50570: pressing pgup or pgdn in any scrollable area irreversably alters scrolling speed. 'page' prop of scroll up/down operators would get stuck once set once by pageup/down keys... Now only take this prop into account if explicitely set, not when its value is inherited from previous run. --- source/blender/editors/interface/view2d_ops.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index d2b2f12c1a5..fa2c1f25cfc 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -447,7 +447,8 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "deltax", 0); RNA_int_set(op->ptr, "deltay", -40); - if (RNA_boolean_get(op->ptr, "page")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page"); + if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) { ARegion *ar = CTX_wm_region(C); RNA_int_set(op->ptr, "deltay", ar->v2d.mask.ymin - ar->v2d.mask.ymax); } @@ -497,7 +498,8 @@ static int view_scrollup_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "deltax", 0); RNA_int_set(op->ptr, "deltay", 40); - if (RNA_boolean_get(op->ptr, "page")) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "page"); + if (RNA_property_is_set(op->ptr, prop) && RNA_property_boolean_get(op->ptr, prop)) { ARegion *ar = CTX_wm_region(C); RNA_int_set(op->ptr, "deltay", BLI_rcti_size_y(&ar->v2d.mask)); } From 3ab8895610be70affb61edf60a07fda8f59e3f74 Mon Sep 17 00:00:00 2001 From: Aaron Date: Wed, 1 Feb 2017 14:56:11 -0500 Subject: [PATCH 10/18] UI: Add missing colon --- release/scripts/startup/bl_ui/properties_render.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 850606eb80b..6d23c07152e 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -377,7 +377,7 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel): sub.active = rd.use_stamp_note sub.prop(rd, "stamp_note_text", text="") if rd.use_sequencer: - layout.label("Sequencer") + layout.label("Sequencer:") layout.prop(rd, "use_stamp_strip_meta") From d4e0557cf1813310e6e41a3ebb1f36f53d916cbe Mon Sep 17 00:00:00 2001 From: Michael Stahre <> Date: Thu, 2 Feb 2017 03:59:21 +0100 Subject: [PATCH 11/18] Fix missing uniform type for python GPU uniform export. Reviewed By: brecht Differential Revision: https://developer.blender.org/D2379 --- source/blender/python/intern/gpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c index 50dd4618166..48230a723d2 100644 --- a/source/blender/python/intern/gpu.c +++ b/source/blender/python/intern/gpu.c @@ -138,6 +138,7 @@ static PyObject *PyInit_gpu(void) PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_EMIT); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_AMB); PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_ALPHA); + PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_MAT_MIR); /* -------------------------------------------------------------------- */ From 7f10a889e33cf5a8a524b4199911ec0d91d176f0 Mon Sep 17 00:00:00 2001 From: Michael Stahre <> Date: Thu, 2 Feb 2017 03:59:11 +0100 Subject: [PATCH 12/18] Fix incorrect spot lamp blend in python GPU uniform export. Reviewed By: brecht Differential Revision: https://developer.blender.org/D2378 --- source/blender/gpu/intern/gpu_material.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index b857aea29ad..4e2043471b6 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -609,7 +609,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode GPU_link(mat, "lamp_visibility_spot", GPU_dynamic_uniform(&lamp->spotsi, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), - GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTSIZE, lamp->ob), + GPU_dynamic_uniform(&lamp->spotbl, GPU_DYNAMIC_LAMP_SPOTBLEND, lamp->ob), inpr, visifac, &visifac); } From 6edfa73f5c34260c29b8c0bdd2e90f4a690eef49 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Wed, 1 Feb 2017 23:46:53 -0500 Subject: [PATCH 13/18] Revert the change of a default in a recent commit This was my own mistake --- source/blender/makesrna/intern/rna_userdef.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 0eab38faca8..e68e67586e9 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3937,7 +3937,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dpi"); - RNA_def_property_range(prop, 16, 256); + RNA_def_property_range(prop, 48, 144); RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); From 86747ff1804e084e9129ec1dd31279b39fc00cd8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 2 Feb 2017 14:32:05 +0100 Subject: [PATCH 14/18] Fix T50535: Cycles render segfault when Explode modifier before hair particle modifier + UV material Tricky issue caused by CDDM_copy() coying MFACE array but not MTFACE which confused logic later on. Now we don't copy ANY tessellation unless it is requested to. Thanks Bastien for help and review! --- .../blender/blenkernel/intern/cdderivedmesh.c | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index f2dd2a3fcf6..fc3e358cb25 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2408,36 +2408,46 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source, int faces_from_tessfaces) int numLoops = source->numLoopData; int numPolys = source->numPolyData; + /* NOTE: Don't copy tessellation faces if not requested explicitly. */ + /* ensure these are created if they are made on demand */ source->getVertDataArray(source, CD_ORIGINDEX); source->getEdgeDataArray(source, CD_ORIGINDEX); - source->getTessFaceDataArray(source, CD_ORIGINDEX); source->getPolyDataArray(source, CD_ORIGINDEX); /* this initializes dm, and copies all non mvert/medge/mface layers */ - DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, + DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, + faces_from_tessfaces ? numTessFaces : 0, 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; + CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts); CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges); - CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces); /* now add mvert/medge/mface layers */ cddm->mvert = source->dupVertArray(source); cddm->medge = source->dupEdgeArray(source); - cddm->mface = source->dupTessFaceArray(source); CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts); CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges); - CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces); - if (!faces_from_tessfaces) + if (!faces_from_tessfaces) { DM_DupPolys(source, dm); - else + } + else { + source->getTessFaceDataArray(source, CD_ORIGINDEX); + CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numTessFaces); + + cddm->mface = source->dupTessFaceArray(source); + CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numTessFaces); + CDDM_tessfaces_to_faces(dm); + } cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP); cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY); From feb588060a6c33c42b3bbf4a5c15283644a342f9 Mon Sep 17 00:00:00 2001 From: raa Date: Thu, 2 Feb 2017 17:30:50 +0300 Subject: [PATCH 15/18] Fix T50497: prop_search not correctly drew in UI (D2473) --- .../editors/interface/interface_layout.c | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 7262b453e02..ca2538022b0 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2078,15 +2078,7 @@ static void ui_litem_estimate_row(uiLayout *litem) for (item = litem->items.first; item; item = item->next) { ui_item_size(item, &itemw, &itemh); - if (item->type == ITEM_BUTTON) { - const uiBut *but = ((uiButtonItem *)item)->but; - const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0'); - - min_size_flag = min_size_flag && icon_only; - } - else { - min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); - } + min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); litem->w += itemw; litem->h = MAX2(itemh, litem->h); @@ -2232,15 +2224,7 @@ static void ui_litem_estimate_column(uiLayout *litem) for (item = litem->items.first; item; item = item->next) { ui_item_size(item, &itemw, &itemh); - if (item->type == ITEM_BUTTON) { - const uiBut *but = ((uiButtonItem *)item)->but; - const bool icon_only = (but->flag & UI_HAS_ICON) && (but->str == NULL || but->str[0] == '\0'); - - min_size_flag = min_size_flag && icon_only; - } - else { - min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); - } + min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); litem->w = MAX2(litem->w, itemw); litem->h += itemh; @@ -3336,6 +3320,14 @@ void ui_layout_add_but(uiLayout *layout, uiBut *but) bitem = MEM_callocN(sizeof(uiButtonItem), "uiButtonItem"); bitem->item.type = ITEM_BUTTON; bitem->but = but; + + int w, h; + ui_item_size((uiItem *)bitem, &w, &h); + /* XXX uiBut hasn't scaled yet + * we can flag the button as not expandable, depending on its size */ + if (w <= 2 * UI_UNIT_X) + bitem->item.flag |= UI_ITEM_MIN; + BLI_addtail(&layout->items, bitem); if (layout->context) { From 9e2dca933e3e1541c5d40a89e10a0277be94e2fe Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 2 Feb 2017 17:00:52 +0100 Subject: [PATCH 16/18] Fix T50524: Basis shapekey editing while rendering bug. Root of the issue was BM_mesh_bm_to_me() breaking application of basis offset to 'child' shapekeys, when called more than once from same BMesh. --- source/blender/bmesh/intern/bmesh_mesh_conv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index bb61f66e267..59ce91a3e70 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -945,6 +945,10 @@ void BM_mesh_bm_to_me( /* propagate edited basis offsets to other shapes */ if (apply_offset) { add_v3_v3(fp, *ofs_pt++); + /* Apply back new coordinates of offsetted shapekeys into BMesh. + * Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, we'll apply diff from previous + * call to BM_mesh_bm_to_me, to shapekey values from *original creation of the BMesh*. See T50524. */ + copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp); } fp += 3; From 33e456b0ce65b07a286e22e2a40570d28a46a443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Thu, 2 Feb 2017 16:04:49 +0100 Subject: [PATCH 17/18] install_deps.sh: don't use backticks The script complained that it could not find the executable "--build-all". --- build_files/build_environment/install_deps.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index c4d6b284c48..ee49f83b38d 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -795,7 +795,7 @@ CXXFLAGS_BACK=$CXXFLAGS if [ "$USE_CXX11" = true ]; then WARNING "You are trying to use c++11, this *should* go smoothely with any very recent distribution However, if you are experiencing linking errors (also when building Blender itself), please try the following: - * Re-run this script with `--build-all --force-all` options. + * Re-run this script with '--build-all --force-all' options. * Ensure your gcc version is at the very least 4.8, if possible you should really rather use gcc-5.1 or above. Please note that until the transition to C++11-built libraries if completed in your distribution, situation will From 9f67367f0aae46f022adb9b47d91c01b35ab9b0f Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 2 Feb 2017 21:37:53 +0100 Subject: [PATCH 18/18] Fix T50084: Adding torus re-orders UV layers. Issue was indeed in join operation, mesh in which we join all others could be re-added to final data after others, leading to undesired re-ordering of CD layers, and existing vertices etc. being shifted away from their original indices, etc. All kind of more or less bad and undesired changes, fixed by always re-inserting destination mesh first. Also cleaned up a bit that code, it was doing some rather non-recommanded things (like allocating zero-sized mem, doing own coocking to remove a data-block from main, etc.). --- source/blender/editors/mesh/meshtools.c | 444 +++++++++++++----------- 1 file changed, 238 insertions(+), 206 deletions(-) diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index b26989113d4..743efb246ab 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -75,26 +75,213 @@ /* join selected meshes into the active mesh, context sensitive * return 0 if no join is made (error) and 1 if the join is done */ +static void join_mesh_single( + Main *bmain, Scene *scene, + Object *ob_dst, Base *base_src, float imat[4][4], + MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp, + CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata, + int totvert, int totedge, int totloop, int totpoly, + Key *key, Key *nkey, + Material **matar, int *matmap, int totcol, + int *vertofs, int *edgeofs, int *loopofs, int *polyofs) +{ + int a, b; + + Mesh *me = base_src->object->data; + MVert *mvert = *mvert_pp; + MEdge *medge = *medge_pp; + MLoop *mloop = *mloop_pp; + MPoly *mpoly = *mpoly_pp; + + if (me->totvert) { + /* merge customdata flag */ + ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag; + + /* standard data */ + CustomData_merge(&me->vdata, vdata, CD_MASK_MESH, CD_DEFAULT, totvert); + CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert); + + /* vertex groups */ + MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT); + + /* NB: vertex groups here are new version */ + if (dvert) { + for (a = 0; a < me->totvert; a++) { + for (b = 0; b < dvert[a].totweight; b++) { + /* Find the old vertex group */ + bDeformGroup *dg, *odg = BLI_findlink(&base_src->object->defbase, dvert[a].dw[b].def_nr); + int index; + if (odg) { + /* Search for a match in the new object, and set new index */ + for (dg = ob_dst->defbase.first, index = 0; dg; dg = dg->next, index++) { + if (STREQ(dg->name, odg->name)) { + dvert[a].dw[b].def_nr = index; + break; + } + } + } + } + } + } + + /* if this is the object we're merging into, no need to do anything */ + if (base_src->object != ob_dst) { + float cmat[4][4]; + + /* watch this: switch matmul order really goes wrong */ + mul_m4_m4m4(cmat, imat, base_src->object->obmat); + + /* transform vertex coordinates into new space */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, mvert++) { + mul_m4_v3(cmat, mvert->co); + } + + /* for each shapekey in destination mesh: + * - if there's a matching one, copy it across (will need to transform vertices into new space...) + * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) + */ + if (key) { + /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { + /* get pointer to where to write data for this mesh in shapekey's data array */ + float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs; + + /* check if this mesh has such a shapekey */ + KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL; + if (okb) { + /* copy this mesh's shapekey to the destination shapekey (need to transform first) */ + float (*ocos)[3] = okb->data; + for (a = 0; a < me->totvert; a++, cos++, ocos++) { + copy_v3_v3(*cos, *ocos); + mul_m4_v3(cmat, *cos); + } + } + else { + /* copy this mesh's vertex coordinates to the destination shapekey */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) { + copy_v3_v3(*cos, mvert->co); + } + } + } + } + } + else { + /* for each shapekey in destination mesh: + * - if it was an 'original', copy the appropriate data from nkey + * - otherwise, copy across plain coordinates (no need to transform coordinates) + */ + if (key) { + for (KeyBlock *kb = key->block.first; kb; kb = kb->next) { + /* get pointer to where to write data for this mesh in shapekey's data array */ + float (*cos)[3] = ((float (*)[3])kb->data) + *vertofs; + + /* check if this was one of the original shapekeys */ + KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; + if (okb) { + /* copy this mesh's shapekey to the destination shapekey */ + float (*ocos)[3] = okb->data; + for (a = 0; a < me->totvert; a++, cos++, ocos++) { + copy_v3_v3(*cos, *ocos); + } + } + else { + /* copy base-coordinates to the destination shapekey */ + for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) { + copy_v3_v3(*cos, mvert->co); + } + } + } + } + } + } + + if (me->totedge) { + CustomData_merge(&me->edata, edata, CD_MASK_MESH, CD_DEFAULT, totedge); + CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge); + + for (a = 0; a < me->totedge; a++, medge++) { + medge->v1 += *vertofs; + medge->v2 += *vertofs; + } + } + + if (me->totloop) { + if (base_src->object != ob_dst) { + MultiresModifierData *mmd; + + multiresModifier_prepare_join(scene, base_src->object, ob_dst); + + if ((mmd = get_multires_modifier(scene, base_src->object, true))) { + ED_object_iter_other(bmain, base_src->object, true, + ED_object_multires_update_totlevels_cb, + &mmd->totlvl); + } + } + + CustomData_merge(&me->ldata, ldata, CD_MASK_MESH, CD_DEFAULT, totloop); + CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop); + + for (a = 0; a < me->totloop; a++, mloop++) { + mloop->v += *vertofs; + mloop->e += *edgeofs; + } + } + + if (me->totpoly) { + if (matmap) { + /* make mapping for materials */ + for (a = 1; a <= base_src->object->totcol; a++) { + Material *ma = give_current_material(base_src->object, a); + + for (b = 0; b < totcol; b++) { + if (ma == matar[b]) { + matmap[a - 1] = b; + break; + } + } + } + } + + CustomData_merge(&me->pdata, pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); + CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly); + + for (a = 0; a < me->totpoly; a++, mpoly++) { + mpoly->loopstart += *loopofs; + mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0; + } + } + + /* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */ + *vertofs += me->totvert; + *mvert_pp += me->totvert; + *edgeofs += me->totedge; + *medge_pp += me->totedge; + *loopofs += me->totloop; + *mloop_pp += me->totloop; + *polyofs += me->totpoly; + *mpoly_pp += me->totpoly; +} + int join_mesh_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); - Material **matar, *ma; + Base *ob_base = CTX_data_active_base(C); + Object *ob = ob_base->object; + Material **matar = NULL, *ma; Mesh *me; - MVert *mvert, *mv; + MVert *mvert = NULL; MEdge *medge = NULL; MPoly *mpoly = NULL; MLoop *mloop = NULL; Key *key, *nkey = NULL; - KeyBlock *kb, *okb, *kbn; - float imat[4][4], cmat[4][4], *fp1, *fp2; + KeyBlock *kb, *kbn; + float imat[4][4]; int a, b, totcol, totmat = 0, totedge = 0, totvert = 0; int totloop = 0, totpoly = 0, vertofs, *matmap = NULL; - int i, j, index, haskey = 0, edgeofs, loopofs, polyofs; + int i, haskey = 0, edgeofs, loopofs, polyofs; bool ok = false; bDeformGroup *dg, *odg; - MDeformVert *dvert; CustomData vdata, edata, fdata, ldata, pdata; if (scene->obedit) { @@ -154,8 +341,10 @@ int join_mesh_exec(bContext *C, wmOperator *op) BKE_mesh_tessface_clear(me); /* new material indices and material array */ - matar = MEM_callocN(sizeof(void *) * totmat, "join_mesh matar"); - if (totmat) matmap = MEM_callocN(sizeof(int) * totmat, "join_mesh matmap"); + if (totmat) { + matar = MEM_callocN(sizeof(*matar) * totmat, "join_mesh matar"); + matmap = MEM_callocN(sizeof(*matmap) * totmat, "join_mesh matmap"); + } totcol = ob->totcol; /* obact materials in new main array, is nicer start! */ @@ -214,7 +403,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) ma = give_current_material(base->object, a); for (b = 0; b < totcol; b++) { - if (ma == matar[b]) break; + if (ma == matar[b]) { + break; + } } if (b == totcol) { matar[b] = ma; @@ -223,8 +414,9 @@ int join_mesh_exec(bContext *C, wmOperator *op) } totcol++; } - if (totcol >= MAXMAT) + if (totcol >= MAXMAT) { break; + } } } @@ -301,187 +493,41 @@ int join_mesh_exec(bContext *C, wmOperator *op) /* inverse transform for all selected meshes in this object */ invert_m4_m4(imat, ob->obmat); - + + /* Add back active mesh first. This allows to keep things similar as they were, as much as possible (i.e. data from + * active mesh will remain first ones in new result of the merge, in same order for CD layers, etc. See also T50084. + */ + join_mesh_single( + bmain, scene, + ob, ob_base, imat, + &mvert, &medge, &mloop, &mpoly, + &vdata, &edata, &ldata, &pdata, + totvert, totedge, totloop, totpoly, + key, nkey, + matar, matmap, totcol, + &vertofs, &edgeofs, &loopofs, &polyofs); + CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { + if (base->object == ob) { + continue; + } /* only join if this is a mesh */ if (base->object->type == OB_MESH) { - me = base->object->data; - - if (me->totvert) { + join_mesh_single( + bmain, scene, + ob, base, imat, + &mvert, &medge, &mloop, &mpoly, + &vdata, &edata, &ldata, &pdata, + totvert, totedge, totloop, totpoly, + key, nkey, + matar, matmap, totcol, + &vertofs, &edgeofs, &loopofs, &polyofs); - /* merge customdata flag */ - ((Mesh *)ob->data)->cd_flag |= me->cd_flag; - - /* standard data */ - CustomData_merge(&me->vdata, &vdata, CD_MASK_MESH, CD_DEFAULT, totvert); - CustomData_copy_data_named(&me->vdata, &vdata, 0, vertofs, me->totvert); - - /* vertex groups */ - dvert = CustomData_get(&vdata, vertofs, CD_MDEFORMVERT); - - /* NB: vertex groups here are new version */ - if (dvert) { - for (i = 0; i < me->totvert; i++) { - for (j = 0; j < dvert[i].totweight; j++) { - /* Find the old vertex group */ - odg = BLI_findlink(&base->object->defbase, dvert[i].dw[j].def_nr); - if (odg) { - /* Search for a match in the new object, and set new index */ - for (dg = ob->defbase.first, index = 0; dg; dg = dg->next, index++) { - if (STREQ(dg->name, odg->name)) { - dvert[i].dw[j].def_nr = index; - break; - } - } - } - } - } - } - - /* if this is the object we're merging into, no need to do anything */ - if (base->object != ob) { - /* watch this: switch matmul order really goes wrong */ - mul_m4_m4m4(cmat, imat, base->object->obmat); - - /* transform vertex coordinates into new space */ - for (a = 0, mv = mvert; a < me->totvert; a++, mv++) { - mul_m4_v3(cmat, mv->co); - } - - /* for each shapekey in destination mesh: - * - if there's a matching one, copy it across (will need to transform vertices into new space...) - * - otherwise, just copy own coordinates of mesh (no need to transform vertex coordinates into new space) - */ - if (key) { - /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */ - for (kb = key->block.first; kb; kb = kb->next) { - /* get pointer to where to write data for this mesh in shapekey's data array */ - fp1 = ((float *)kb->data) + (vertofs * 3); - - /* check if this mesh has such a shapekey */ - okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL; - - if (okb) { - /* copy this mesh's shapekey to the destination shapekey (need to transform first) */ - fp2 = ((float *)(okb->data)); - for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) { - copy_v3_v3(fp1, fp2); - mul_m4_v3(cmat, fp1); - } - } - else { - /* copy this mesh's vertex coordinates to the destination shapekey */ - mv = mvert; - for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) { - copy_v3_v3(fp1, mv->co); - } - } - } - } - } - else { - /* for each shapekey in destination mesh: - * - if it was an 'original', copy the appropriate data from nkey - * - otherwise, copy across plain coordinates (no need to transform coordinates) - */ - if (key) { - for (kb = key->block.first; kb; kb = kb->next) { - /* get pointer to where to write data for this mesh in shapekey's data array */ - fp1 = ((float *)kb->data) + (vertofs * 3); - - /* check if this was one of the original shapekeys */ - okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL; - if (okb) { - /* copy this mesh's shapekey to the destination shapekey */ - fp2 = ((float *)(okb->data)); - for (a = 0; a < me->totvert; a++, fp1 += 3, fp2 += 3) { - copy_v3_v3(fp1, fp2); - } - } - else { - /* copy base-coordinates to the destination shapekey */ - mv = mvert; - for (a = 0; a < me->totvert; a++, fp1 += 3, mv++) { - copy_v3_v3(fp1, mv->co); - } - } - } - } - } - - /* advance mvert pointer to end of base mesh's data */ - mvert += me->totvert; - } - - if (me->totedge) { - CustomData_merge(&me->edata, &edata, CD_MASK_MESH, CD_DEFAULT, totedge); - CustomData_copy_data_named(&me->edata, &edata, 0, edgeofs, me->totedge); - - for (a = 0; a < me->totedge; a++, medge++) { - medge->v1 += vertofs; - medge->v2 += vertofs; - } - } - - if (me->totloop) { - if (base->object != ob) { - MultiresModifierData *mmd; - - multiresModifier_prepare_join(scene, base->object, ob); - - if ((mmd = get_multires_modifier(scene, base->object, true))) { - ED_object_iter_other(bmain, base->object, true, - ED_object_multires_update_totlevels_cb, - &mmd->totlvl); - } - } - - CustomData_merge(&me->ldata, &ldata, CD_MASK_MESH, CD_DEFAULT, totloop); - CustomData_copy_data_named(&me->ldata, &ldata, 0, loopofs, me->totloop); - - for (a = 0; a < me->totloop; a++, mloop++) { - mloop->v += vertofs; - mloop->e += edgeofs; - } - } - - if (me->totpoly) { - if (totmat) { - /* make mapping for materials */ - for (a = 1; a <= base->object->totcol; a++) { - ma = give_current_material(base->object, a); - - for (b = 0; b < totcol; b++) { - if (ma == matar[b]) { - matmap[a - 1] = b; - break; - } - } - } - } - - CustomData_merge(&me->pdata, &pdata, CD_MASK_MESH, CD_DEFAULT, totpoly); - CustomData_copy_data_named(&me->pdata, &pdata, 0, polyofs, me->totpoly); - - for (a = 0; a < me->totpoly; a++, mpoly++) { - mpoly->loopstart += loopofs; - mpoly->mat_nr = matmap ? matmap[(int)mpoly->mat_nr] : 0; - } - - polyofs += me->totpoly; - } - - /* these are used for relinking (cannot be set earlier, - * or else reattaching goes wrong) - */ - vertofs += me->totvert; - edgeofs += me->totedge; - loopofs += me->totloop; - /* free base, now that data is merged */ - if (base->object != ob) + if (base->object != ob) { ED_base_object_free_and_unlink(bmain, scene, base); + } } } CTX_DATA_END; @@ -529,34 +575,20 @@ int join_mesh_exec(bContext *C, wmOperator *op) if (totcol) { me->mat = matar; - ob->mat = MEM_callocN(sizeof(void *) * totcol, "join obmatar"); - ob->matbits = MEM_callocN(sizeof(char) * totcol, "join obmatbits"); + ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar"); + ob->matbits = MEM_callocN(sizeof(*ob->matbits) * totcol, "join obmatbits"); + MEM_freeN(matmap); } - else - MEM_freeN(matar); - + ob->totcol = me->totcol = totcol; - if (matmap) MEM_freeN(matmap); - /* other mesh users */ test_all_objects_materials(bmain, (ID *)me); /* free temp copy of destination shapekeys (if applicable) */ if (nkey) { - /* XXX 2.5 Animato */ -#if 0 - /* free it's ipo too - both are not actually freed from memory yet as ID-blocks */ - if (nkey->ipo) { - BKE_ipo_free(nkey->ipo); - BLI_remlink(&bmain->ipo, nkey->ipo); - MEM_freeN(nkey->ipo); - } -#endif - - BKE_key_free(nkey); - BLI_remlink(&bmain->key, nkey); - MEM_freeN(nkey); + /* We can assume nobody is using that ID currently. */ + BKE_libblock_free_ex(bmain, nkey, false, false); } /* ensure newly inserted keys are time sorted */ @@ -564,7 +596,7 @@ int join_mesh_exec(bContext *C, wmOperator *op) BKE_key_sort(key); } - DAG_relations_tag_update(bmain); // removed objects, need to rebuild dag + DAG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);