diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.cc | 33 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/attribute.cc | 55 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/dynamicpaint.c | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/geometry_set_instances.cc | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/gpencil_modifier.c | 43 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/image.cc | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/lib_override.cc | 38 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_boolean_convert.cc | 24 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_calc_edges.cc | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_wrapper.cc | 23 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/nla.c | 45 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh.c | 50 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subdiv_mesh.c | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/subdiv_modifier.c | 62 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/tracking.c | 10 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/unit.c | 16 |
16 files changed, 263 insertions, 160 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 8496692ceb3..b3a9d894944 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -52,6 +52,7 @@ #include "BKE_object.h" #include "BKE_object_deform.h" #include "BKE_paint.h" +#include "BKE_subdiv_modifier.h" #include "BLI_sys_types.h" /* for intptr_t support */ @@ -598,10 +599,10 @@ static bool mesh_has_modifier_final_normals(const Mesh *mesh_input, /* Test if mesh has the required loop normals, in case an additional modifier * evaluation from another instance or from an operator requests it but the * initial normals were not loop normals. */ - const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); + const bool calc_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || + (final_datamask->lmask & CD_MASK_NORMAL) != 0); - return (!do_loop_normals || CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)); + return (!calc_loop_normals || CustomData_has_layer(&mesh_final->ldata, CD_NORMAL)); } static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, @@ -610,16 +611,19 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input, Mesh *mesh_final) { /* Compute normals. */ - const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); + const bool calc_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || + (final_datamask->lmask & CD_MASK_NORMAL) != 0); /* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */ - mesh_final->runtime.subsurf_do_loop_normals = do_loop_normals; + SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime.subsurf_runtime_data; + if (subsurf_runtime_data) { + subsurf_runtime_data->calc_loop_normals = calc_loop_normals; + } - if (do_loop_normals) { + if (calc_loop_normals) { /* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). In case * of deferred CPU subdivision, this will be computed when the wrapper is generated. */ - if (mesh_final->runtime.subsurf_resolution == 0) { + if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { BKE_mesh_calc_normals_split(mesh_final); } } @@ -1266,15 +1270,18 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, return; } - const bool do_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 || - (final_datamask->lmask & CD_MASK_NORMAL) != 0); + const bool calc_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 || + (final_datamask->lmask & CD_MASK_NORMAL) != 0); - mesh_final->runtime.subsurf_do_loop_normals = do_loop_normals; + SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime.subsurf_runtime_data; + if (subsurf_runtime_data) { + subsurf_runtime_data->calc_loop_normals = calc_loop_normals; + } - if (do_loop_normals) { + if (calc_loop_normals) { /* Compute loop normals. In case of deferred CPU subdivision, this will be computed when the * wrapper is generated. */ - if (mesh_final->runtime.subsurf_resolution == 0) { + if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) { BKE_mesh_calc_normals_split(mesh_final); } } diff --git a/source/blender/blenkernel/intern/attribute.cc b/source/blender/blenkernel/intern/attribute.cc index b2ea8b833b3..7c09b4a4ce3 100644 --- a/source/blender/blenkernel/intern/attribute.cc +++ b/source/blender/blenkernel/intern/attribute.cc @@ -208,53 +208,36 @@ CustomDataLayer *BKE_id_attribute_new( return (index == -1) ? nullptr : &(customdata->layers[index]); } -CustomDataLayer *BKE_id_attribute_duplicate(ID *id, CustomDataLayer *layer, ReportList *reports) +CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList *reports) { - DomainInfo info[ATTR_DOMAIN_NUM]; - get_domains(id, info); - - eCustomDataType type = (eCustomDataType)layer->type; - eAttrDomain domain = BKE_id_attribute_domain(id, layer); - - CustomData *customdata = info[domain].customdata; - if (customdata == nullptr) { - BKE_report(reports, RPT_ERROR, "Attribute domain not supported by this geometry type"); + const CustomDataLayer *src_layer = BKE_id_attribute_search( + id, name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL); + if (src_layer == nullptr) { + BKE_report(reports, RPT_ERROR, "Attribute is not part of this geometry"); return nullptr; } - char name[MAX_CUSTOMDATA_LAYER_NAME]; - char uniquename[MAX_CUSTOMDATA_LAYER_NAME]; + const eCustomDataType type = (eCustomDataType)src_layer->type; + const eAttrDomain domain = BKE_id_attribute_domain(id, src_layer); /* Make a copy of name in case CustomData API reallocates the layers. */ - BLI_strncpy(name, layer->name, MAX_CUSTOMDATA_LAYER_NAME); - BKE_id_attribute_calc_unique_name(id, layer->name, uniquename); + const std::string name_copy = name; - switch (GS(id->name)) { - case ID_ME: { - Mesh *me = (Mesh *)id; - BMEditMesh *em = me->edit_mesh; - if (em != nullptr) { - BM_data_layer_add_named(em->bm, customdata, type, uniquename); - } - else { - CustomData_add_layer_named( - customdata, type, CD_DEFAULT, nullptr, info[domain].length, uniquename); - } - break; - } - default: { - CustomData_add_layer_named( - customdata, type, CD_DEFAULT, nullptr, info[domain].length, uniquename); - break; - } + DomainInfo info[ATTR_DOMAIN_NUM]; + get_domains(id, info); + CustomData *customdata = info[domain].customdata; + + CustomDataLayer *new_layer = BKE_id_attribute_new(id, name_copy.c_str(), type, domain, reports); + if (new_layer == nullptr) { + return nullptr; } - int from_index = CustomData_get_named_layer_index(customdata, type, name); - int to_index = CustomData_get_named_layer_index(customdata, type, uniquename); + const int from_index = CustomData_get_named_layer_index(customdata, type, name_copy.c_str()); + const int to_index = CustomData_get_named_layer_index(customdata, type, new_layer->name); CustomData_copy_data_layer( customdata, customdata, from_index, to_index, 0, 0, info[domain].length); - return (to_index == -1) ? nullptr : &(customdata->layers[to_index]); + return new_layer; } bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports) @@ -317,7 +300,7 @@ CustomDataLayer *BKE_id_attribute_find(const ID *id, return nullptr; } -CustomDataLayer *BKE_id_attribute_search(const ID *id, +CustomDataLayer *BKE_id_attribute_search(ID *id, const char *name, const eCustomDataMask type_mask, const eAttrDomainMask domain_mask) diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 48f2d66c1cd..e5bb70f8cda 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2024,13 +2024,13 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object * settings.use_threading = (sData->total_points > 1000); BLI_task_parallel_range( 0, sData->total_points, &data, dynamic_paint_apply_surface_wave_cb, &settings); - BKE_mesh_normals_tag_dirty(mesh); + BKE_mesh_normals_tag_dirty(result); } /* displace */ if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) { dynamicPaint_applySurfaceDisplace(surface, result); - BKE_mesh_normals_tag_dirty(mesh); + BKE_mesh_normals_tag_dirty(result); } } } diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index d3c3f41779a..2d6e0e05a97 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -32,9 +32,7 @@ static void add_final_mesh_as_geometry_component(const Object &object, GeometryS if (mesh != nullptr) { BKE_mesh_wrapper_ensure_mdata(mesh); - - MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); - mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly); + geometry_set.replace_mesh(mesh, GeometryOwnershipType::ReadOnly); } } diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index faafd1e1040..0bf5418ea8f 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -647,32 +647,38 @@ static bGPdata *gpencil_copy_structure_for_eval(bGPdata *gpd) return gpd_eval; } -static void copy_frame_to_eval_cb(bGPDlayer *UNUSED(gpl), +static void copy_frame_to_eval_ex(bGPDframe *gpf_orig, bGPDframe *gpf_eval) +{ + /* Free any existing eval stroke data. This happens in case we have a single user on the data + * block and the strokes have not been deleted. */ + if (!BLI_listbase_is_empty(&gpf_eval->strokes)) { + BKE_gpencil_free_strokes(gpf_eval); + } + /* Copy strokes to eval frame and update internal orig pointers. */ + BKE_gpencil_frame_copy_strokes(gpf_orig, gpf_eval); + BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval); +} + +static void copy_frame_to_eval_cb(bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *UNUSED(gps), void *UNUSED(thunk)) { - /* Early return when callback is not provided with a frame. */ - if (gpf == NULL) { + /* Early return when callback: + * - Is not provided with a frame. + * - When the frame is the layer's active frame (already handled in + * gpencil_copy_visible_frames_to_eval). + */ + if (gpf == NULL || gpf == gpl->actframe) { return; } - /* Free any existing eval stroke data. This happens in case we have a single user on the data - * block and the strokes have not been deleted. */ - if (!BLI_listbase_is_empty(&gpf->strokes)) { - BKE_gpencil_free_strokes(gpf); - } - - /* Get original frame. */ - bGPDframe *gpf_orig = gpf->runtime.gpf_orig; - /* Copy strokes to eval frame and update internal orig pointers. */ - BKE_gpencil_frame_copy_strokes(gpf_orig, gpf); - BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf); + copy_frame_to_eval_ex(gpf->runtime.gpf_orig, gpf); } static void gpencil_copy_visible_frames_to_eval(Depsgraph *depsgraph, Scene *scene, Object *ob) { - /* Remap layers' active frame with time modifiers applied. */ + /* Remap layers active frame with time modifiers applied. */ bGPdata *gpd_eval = ob->data; LISTBASE_FOREACH (bGPDlayer *, gpl_eval, &gpd_eval->layers) { bGPDframe *gpf_eval = gpl_eval->actframe; @@ -680,9 +686,14 @@ static void gpencil_copy_visible_frames_to_eval(Depsgraph *depsgraph, Scene *sce if (gpf_eval == NULL || gpf_eval->framenum != remap_cfra) { gpl_eval->actframe = BKE_gpencil_layer_frame_get(gpl_eval, remap_cfra, GP_GETFRAME_USE_PREV); } + /* Always copy active frame to eval, because the modifiers always evaluate the active frame, + * even if it's not visible (e.g. the layer is hidden).*/ + if (gpl_eval->actframe != NULL) { + copy_frame_to_eval_ex(gpl_eval->actframe->runtime.gpf_orig, gpl_eval->actframe); + } } - /* Copy only visible frames to evaluated version. */ + /* Copy visible frames that are not the active one to evaluated version. */ BKE_gpencil_visible_stroke_advanced_iter( NULL, ob, copy_frame_to_eval_cb, NULL, NULL, true, scene->r.cfra); } diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc index 06a5d877882..0c1f01c3796 100644 --- a/source/blender/blenkernel/intern/image.cc +++ b/source/blender/blenkernel/intern/image.cc @@ -1730,7 +1730,7 @@ static void stampdata_from_template(StampData *stamp_data, stamp_data->file[0] = '\0'; } if (scene->r.stamp & R_STAMP_NOTE) { - SNPRINTF(stamp_data->note, "%s", stamp_data_template->note); + STRNCPY(stamp_data->note, stamp_data_template->note); } else { stamp_data->note[0] = '\0'; @@ -3895,7 +3895,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame) } if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D) { - IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]); + IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], ibuf_arr.data(), &ibuf_arr[1]); } for (int i = 0; i < totviews; i++) { @@ -4064,7 +4064,7 @@ static ImBuf *image_load_image_file( /* multi-views/multi-layers OpenEXR files directly populate ima, and return null ibuf... */ if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D && ibuf_arr[0] && tot_viewfiles == 1 && totviews >= 2) { - IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]); + IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], ibuf_arr.data(), &ibuf_arr[1]); } /* return the original requested ImBuf */ diff --git a/source/blender/blenkernel/intern/lib_override.cc b/source/blender/blenkernel/intern/lib_override.cc index aa43ca94c99..22012662180 100644 --- a/source/blender/blenkernel/intern/lib_override.cc +++ b/source/blender/blenkernel/intern/lib_override.cc @@ -21,8 +21,10 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" +#include "BKE_anim_data.h" #include "BKE_armature.h" #include "BKE_collection.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_idtype.h" #include "BKE_key.h" @@ -312,7 +314,6 @@ bool BKE_lib_override_library_is_user_edited(const ID *id) bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id) { - if (ID_IS_OVERRIDE_LIBRARY(id)) { const ID *override_owner_id; lib_override_get(bmain, id, &override_owner_id); @@ -322,6 +323,34 @@ bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id) return false; } +bool BKE_lib_override_library_property_is_animated(const ID *id, + const IDOverrideLibraryProperty *override_prop, + const PropertyRNA *override_rna_prop, + const int rnaprop_index) +{ + AnimData *anim_data = BKE_animdata_from_id(id); + if (anim_data != nullptr) { + struct FCurve *fcurve; + char *index_token_start = const_cast<char *>( + RNA_path_array_index_token_find(override_prop->rna_path, override_rna_prop)); + if (index_token_start != nullptr) { + const char index_token_start_backup = *index_token_start; + *index_token_start = '\0'; + fcurve = BKE_animadata_fcurve_find_by_rna_path( + anim_data, override_prop->rna_path, rnaprop_index, nullptr, nullptr); + *index_token_start = index_token_start_backup; + } + else { + fcurve = BKE_animadata_fcurve_find_by_rna_path( + anim_data, override_prop->rna_path, 0, nullptr, nullptr); + } + if (fcurve != nullptr) { + return true; + } + } + return false; +} + static int foreachid_is_hierarchy_leaf_fn(LibraryIDLinkCallbackData *cb_data) { ID *id_owner = cb_data->id_owner; @@ -2677,11 +2706,12 @@ IDOverrideLibraryProperty *BKE_lib_override_library_property_get(IDOverrideLibra bool BKE_lib_override_rna_property_find(PointerRNA *idpoin, const IDOverrideLibraryProperty *library_prop, PointerRNA *r_override_poin, - PropertyRNA **r_override_prop) + PropertyRNA **r_override_prop, + int *r_index) { BLI_assert(RNA_struct_is_ID(idpoin->type) && ID_IS_OVERRIDE_LIBRARY(idpoin->data)); - return RNA_path_resolve_property( - idpoin, library_prop->rna_path, r_override_poin, r_override_prop); + return RNA_path_resolve_property_full( + idpoin, library_prop->rna_path, r_override_poin, r_override_prop, r_index); } void lib_override_library_property_copy(IDOverrideLibraryProperty *op_dst, diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index 14bd6aa5b2f..a1ef2d2e6b5 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -791,7 +791,8 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes, Span<Array<short>> material_remaps, const bool use_self, const bool hole_tolerant, - const int boolean_mode) + const int boolean_mode, + Vector<int> *r_intersecting_edges) { #ifdef WITH_GMP BLI_assert(meshes.size() == transforms.size()); @@ -828,7 +829,23 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes, write_obj_mesh(m_out, "m_out"); } - return imesh_to_mesh(&m_out, mim); + Mesh *result = imesh_to_mesh(&m_out, mim); + + /* Store intersecting edge indices. */ + if (r_intersecting_edges != nullptr) { + for (int fi : m_out.face_index_range()) { + const Face &face = *m_out.face(fi); + const MPoly &poly = result->mpoly[fi]; + for (int corner_i : face.index_range()) { + if (face.is_intersect[corner_i]) { + int e_index = result->mloop[poly.loopstart + corner_i].e; + r_intersecting_edges->append(e_index); + } + } + } + } + + return result; #else // WITH_GMP UNUSED_VARS(meshes, transforms, @@ -836,7 +853,8 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes, target_transform, use_self, hole_tolerant, - boolean_mode); + boolean_mode, + r_intersecting_edges); return nullptr; #endif // WITH_GMP } diff --git a/source/blender/blenkernel/intern/mesh_calc_edges.cc b/source/blender/blenkernel/intern/mesh_calc_edges.cc index 5895eb7fd71..31e20750cf2 100644 --- a/source/blender/blenkernel/intern/mesh_calc_edges.cc +++ b/source/blender/blenkernel/intern/mesh_calc_edges.cc @@ -81,7 +81,7 @@ static void add_existing_edges_to_hash_maps(Mesh *mesh, { /* Assume existing edges are valid. */ threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) { - const int task_index = &edge_map - &edge_maps[0]; + const int task_index = &edge_map - edge_maps.data(); for (const MEdge &edge : Span(mesh->medge, mesh->totedge)) { OrderedEdge ordered_edge{edge.v1, edge.v2}; /* Only add the edge when it belongs into this map. */ @@ -98,7 +98,7 @@ static void add_polygon_edges_to_hash_maps(Mesh *mesh, { const Span<MLoop> loops{mesh->mloop, mesh->totloop}; threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) { - const int task_index = &edge_map - &edge_maps[0]; + const int task_index = &edge_map - edge_maps.data(); for (const MPoly &poly : Span(mesh->mpoly, mesh->totpoly)) { Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop); const MLoop *prev_loop = &poly_loops.last(); @@ -131,7 +131,7 @@ static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edg } threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) { - const int task_index = &edge_map - &edge_maps[0]; + const int task_index = &edge_map - edge_maps.data(); int new_edge_index = edge_index_offsets[task_index]; for (EdgeMap::MutableItem item : edge_map.items()) { diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc index c505a74724b..fdebf1d6a26 100644 --- a/source/blender/blenkernel/intern/mesh_wrapper.cc +++ b/source/blender/blenkernel/intern/mesh_wrapper.cc @@ -314,28 +314,23 @@ static Mesh *mesh_wrapper_ensure_subdivision(const Object *ob, Mesh *me) return me; } + SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime; + if (runtime_data == nullptr || runtime_data->settings.level == 0) { + return me; + } + /* Initialize the settings before ensuring the descriptor as this is checked to decide whether * subdivision is needed at all, and checking the descriptor status might involve checking if the * data is out-of-date, which is a very expensive operation. */ SubdivToMeshSettings mesh_settings; - mesh_settings.resolution = me->runtime.subsurf_resolution; - mesh_settings.use_optimal_display = me->runtime.subsurf_use_optimal_display; + mesh_settings.resolution = runtime_data->resolution; + mesh_settings.use_optimal_display = runtime_data->use_optimal_display; if (mesh_settings.resolution < 3) { return me; } - const bool apply_render = me->runtime.subsurf_apply_render; - - SubdivSettings subdiv_settings; - BKE_subsurf_modifier_subdiv_settings_init(&subdiv_settings, smd, apply_render); - if (subdiv_settings.level == 0) { - return me; - } - - SubsurfRuntimeData *runtime_data = BKE_subsurf_modifier_ensure_runtime(smd); - - Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(smd, &subdiv_settings, me, false); + Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, me, false); if (subdiv == nullptr) { /* Happens on bad topology, but also on empty input mesh. */ return me; @@ -358,7 +353,7 @@ static Mesh *mesh_wrapper_ensure_subdivision(const Object *ob, Mesh *me) CustomData_set_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); CustomData_set_layer_flag(&subdiv_mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); } - else if (me->runtime.subsurf_do_loop_normals) { + else if (runtime_data->calc_loop_normals) { BKE_mesh_calc_normals_split(subdiv_mesh); } diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index a5f6c453ed4..8f54d71108a 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -244,24 +244,42 @@ void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, const ListBase *src, const } } -static void update_active_strip_from_listbase(AnimData *adt_dest, - NlaTrack *track_dest, - const NlaStrip *active_strip, - const ListBase /* NlaStrip */ *strips_source) +/** + * Find `active_strip` in `strips_source`, then return the strip with the same + * index from `strips_dest`. + */ +static NlaStrip *find_active_strip_from_listbase(const NlaStrip *active_strip, + const ListBase /* NlaStrip */ *strips_source, + const ListBase /* NlaStrip */ *strips_dest) { - NlaStrip *strip_dest = track_dest->strips.first; + NlaStrip *strip_dest = strips_dest->first; LISTBASE_FOREACH (const NlaStrip *, strip_source, strips_source) { - if (strip_source == active_strip) { - adt_dest->actstrip = strip_dest; - return; + if (strip_dest == NULL) { + /* The tracks are assumed to have an equal number of strips, but this is not the case when + * dragging multiple strips. The transform system merges the selected strips into one + * meta-strip, reducing the number of strips in `track_dest`. */ + break; } - - if (strip_source->type == NLASTRIP_TYPE_META) { - update_active_strip_from_listbase(adt_dest, track_dest, active_strip, &strip_source->strips); + if (strip_source == active_strip) { + return strip_dest; + } + + const bool src_is_meta = strip_source->type == NLASTRIP_TYPE_META; + const bool dst_is_meta = strip_dest->type == NLASTRIP_TYPE_META; + BLI_assert_msg(src_is_meta == dst_is_meta, + "Expecting topology of source and destination strips to be equal"); + if (src_is_meta && dst_is_meta) { + NlaStrip *found_in_meta = find_active_strip_from_listbase( + active_strip, &strip_source->strips, &strip_dest->strips); + if (found_in_meta != NULL) { + return found_in_meta; + } } strip_dest = strip_dest->next; } + + return NULL; } /* Set adt_dest->actstrip to the strip with the same index as adt_source->actstrip. */ @@ -272,8 +290,9 @@ static void update_active_strip(AnimData *adt_dest, { BLI_assert(BLI_listbase_count(&track_source->strips) == BLI_listbase_count(&track_dest->strips)); - update_active_strip_from_listbase( - adt_dest, track_dest, adt_source->actstrip, &track_source->strips); + NlaStrip *active_strip = find_active_strip_from_listbase( + adt_source->actstrip, &track_source->strips, &track_dest->strips); + adt_dest->actstrip = active_strip; } /* Set adt_dest->act_track to the track with the same index as adt_source->act_track. */ diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 8c9db339753..3b20bdc826c 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1391,8 +1391,7 @@ void pbvh_free_draw_buffers(PBVH *pbvh, PBVHNode *node) } } -static void pbvh_update_draw_buffers( - PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag, bool full_render) +static void pbvh_check_draw_layout(PBVH *pbvh) { const CustomData *vdata; const CustomData *ldata; @@ -1420,10 +1419,14 @@ static void pbvh_update_draw_buffers( break; } - const bool active_attrs_only = !full_render; - - /* rebuild all draw buffers if attribute layout changed */ - if (GPU_pbvh_attribute_names_update(pbvh->type, pbvh->vbo_id, vdata, ldata, active_attrs_only)) { + /* Rebuild all draw buffers if attribute layout changed. + * + * NOTE: The optimization where we only send active attributes + * to the GPU in workbench mode is disabled due to bugs + * (there's no guarantee there isn't another EEVEE viewport which would + * free the draw buffers and corrupt the draw cache). + */ + if (GPU_pbvh_attribute_names_update(pbvh->type, pbvh->vbo_id, vdata, ldata, false)) { /* attribute layout changed; force rebuild */ for (int i = 0; i < pbvh->totnode; i++) { PBVHNode *node = pbvh->nodes + i; @@ -1433,6 +1436,33 @@ static void pbvh_update_draw_buffers( } } } +} + +static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag) +{ + const CustomData *vdata; + + if (!pbvh->vbo_id) { + pbvh->vbo_id = GPU_pbvh_make_format(); + } + + switch (pbvh->type) { + case PBVH_BMESH: + if (!pbvh->bm) { + /* BMesh hasn't been created yet */ + return; + } + + vdata = &pbvh->bm->vdata; + break; + case PBVH_FACES: + vdata = pbvh->vdata; + break; + case PBVH_GRIDS: + vdata = NULL; + break; + } + UNUSED_VARS(vdata); if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) { /* Free buffers uses OpenGL, so not in parallel. */ @@ -2837,10 +2867,8 @@ void BKE_pbvh_draw_cb(PBVH *pbvh, PBVHFrustumPlanes *draw_frustum, void (*draw_fn)(void *user_data, GPU_PBVH_Buffers *buffers), void *user_data, - bool full_render) + bool UNUSED(full_render)) { - pbvh->draw_cache_invalid = false; - PBVHNode **nodes; int totnode; int update_flag = 0; @@ -2862,9 +2890,11 @@ void BKE_pbvh_draw_cb(PBVH *pbvh, update_flag = PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers; } + pbvh_check_draw_layout(pbvh); + /* Update draw buffers. */ if (totnode != 0 && (update_flag & (PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers))) { - pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag, full_render); + pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag); } MEM_SAFE_FREE(nodes); diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index ca4130d6bc4..433bad34479 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -5,9 +5,6 @@ * \ingroup bke */ -#include "BKE_mesh.h" -#include "BKE_subdiv_mesh.h" - #include "atomic_ops.h" #include "DNA_key_types.h" @@ -24,6 +21,7 @@ #include "BKE_subdiv.h" #include "BKE_subdiv_eval.h" #include "BKE_subdiv_foreach.h" +#include "BKE_subdiv_mesh.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/blenkernel/intern/subdiv_modifier.c b/source/blender/blenkernel/intern/subdiv_modifier.c index e43da956ce5..f5423dccc0f 100644 --- a/source/blender/blenkernel/intern/subdiv_modifier.c +++ b/source/blender/blenkernel/intern/subdiv_modifier.c @@ -3,8 +3,6 @@ #include "BKE_subdiv_modifier.h" -#include "BLI_session_uuid.h" - #include "MEM_guardedalloc.h" #include "DNA_mesh_types.h" @@ -21,22 +19,40 @@ #include "opensubdiv_capi.h" -void BKE_subsurf_modifier_subdiv_settings_init(SubdivSettings *settings, - const SubsurfModifierData *smd, - const bool use_render_params) +bool BKE_subsurf_modifier_runtime_init(SubsurfModifierData *smd, const bool use_render_params) { const int requested_levels = (use_render_params) ? smd->renderLevels : smd->levels; - settings->is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE); - settings->is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision); - settings->level = settings->is_simple ? - 1 : - (settings->is_adaptive ? smd->quality : requested_levels); - settings->use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease); - settings->vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf( + SubdivSettings settings; + settings.is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE); + settings.is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision); + settings.level = settings.is_simple ? 1 : + (settings.is_adaptive ? smd->quality : requested_levels); + settings.use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease); + settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf( smd->boundary_smooth); - settings->fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth( + settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth( smd->uv_smooth); + + SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime; + if (settings.level == 0) { + /* Modifier is effectively disabled, but still update settings if runtime data + * was already allocated. */ + if (runtime_data) { + runtime_data->settings = settings; + } + + return false; + } + else { + /* Allocate runtime data if it did not exist yet. */ + if (runtime_data == NULL) { + runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime"); + smd->modifier.runtime = runtime_data; + } + runtime_data->settings = settings; + return true; + } } static ModifierData *modifier_get_last_enabled_for_mode(const Scene *scene, @@ -133,37 +149,27 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene, bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh) { - return BLI_session_uuid_is_generated(&mesh->runtime.subsurf_session_uuid); + SubsurfRuntimeData *runtime_data = mesh->runtime.subsurf_runtime_data; + return runtime_data && runtime_data->has_gpu_subdiv; } void (*BKE_subsurf_modifier_free_gpu_cache_cb)(Subdiv *subdiv) = NULL; -Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(const SubsurfModifierData *smd, - const SubdivSettings *subdiv_settings, +Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data, const Mesh *mesh, const bool for_draw_code) { - SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime; if (runtime_data->subdiv && runtime_data->set_by_draw_code != for_draw_code) { BKE_subdiv_free(runtime_data->subdiv); runtime_data->subdiv = NULL; } - Subdiv *subdiv = BKE_subdiv_update_from_mesh(runtime_data->subdiv, subdiv_settings, mesh); + Subdiv *subdiv = BKE_subdiv_update_from_mesh( + runtime_data->subdiv, &runtime_data->settings, mesh); runtime_data->subdiv = subdiv; runtime_data->set_by_draw_code = for_draw_code; return subdiv; } -SubsurfRuntimeData *BKE_subsurf_modifier_ensure_runtime(SubsurfModifierData *smd) -{ - SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime; - if (runtime_data == NULL) { - runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime"); - smd->modifier.runtime = runtime_data; - } - return runtime_data; -} - int BKE_subsurf_modifier_eval_required_mode(bool is_final_render, bool is_edit_mode) { if (is_final_render) { diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index f9d3a44e5cb..8b462cba7ed 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -336,7 +336,11 @@ void BKE_tracking_settings_init(MovieTracking *tracking) tracking->stabilization.filter = TRACKING_FILTER_BILINEAR; tracking->stabilization.flag |= TRACKING_SHOW_STAB_TRACKS; - BKE_tracking_object_add(tracking, "Camera"); + /* Descending order of average error: tracks with the highest error are on top. */ + tracking->dopesheet.sort_method = TRACKING_DOPE_SORT_AVERAGE_ERROR; + tracking->dopesheet.flag |= TRACKING_DOPE_SORT_INVERSE; + + BKE_tracking_object_add(tracking, DATA_("Camera")); } ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking) @@ -2904,6 +2908,10 @@ static int channels_average_error_sort(const void *a, const void *b) return 1; } + if (channel_a->track->error == channel_b->track->error) { + return channels_alpha_sort(a, b); + } + return 0; } diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 557fb2568fe..b31632f0234 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -462,11 +462,6 @@ static size_t unit_as_string(char *str, double value_conv = (value / unit->scalar) - unit->bias; bool strip_skip = false; - /* Adjust precision to expected number of significant digits. - * Note that here, we shall not have to worry about very big/small numbers, units are expected - * to replace 'scientific notation' in those cases. */ - prec -= integer_digits_d(value_conv); - /* Negative precision is used to disable stripping of zeroes. * This reduces text jumping when changing values. */ if (prec < 0) { @@ -474,6 +469,11 @@ static size_t unit_as_string(char *str, prec *= -1; } + /* Adjust precision to expected number of significant digits. + * Note that here, we shall not have to worry about very big/small numbers, units are expected + * to replace 'scientific notation' in those cases. */ + prec -= integer_digits_d(value_conv); + CLAMP(prec, 0, 6); /* Convert to a string. */ @@ -491,10 +491,10 @@ static size_t unit_as_string(char *str, while (i > 0 && str[i] == '0') { /* 4.300 -> 4.3 */ str[i--] = pad; } - } - if (i > 0 && str[i] == '.') { /* 10. -> 10 */ - str[i--] = pad; + if (i > 0 && str[i] == '.') { /* 10. -> 10 */ + str[i--] = pad; + } } } |