Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/DerivedMesh.c
| Show First 20 Lines • Show All 1,713 Lines • ▼ Show 20 Lines | static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, | ||||
| /* Return final mesh. */ | /* Return final mesh. */ | ||||
| *r_final = mesh_final; | *r_final = mesh_final; | ||||
| if (r_cage) { | if (r_cage) { | ||||
| *r_cage = mesh_cage; | *r_cage = mesh_cage; | ||||
| } | } | ||||
| } | } | ||||
| static void assign_object_mesh_eval(Object *object) | static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob, Mesh *mesh_eval) | ||||
| { | |||||
| BLI_assert(object->id.tag & LIB_TAG_COPIED_ON_WRITE); | |||||
| Mesh *mesh = (Mesh *)object->data; | |||||
| Mesh *mesh_eval = object->runtime.mesh_eval; | |||||
| /* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result | |||||
| * is not guaranteed to be owned by object. | |||||
| * | |||||
| * Check ownership now, since later on we can not go to a mesh owned by someone else via object's | |||||
| * runtime: this could cause access freed data on depsgraph destruction (mesh who owns the final | |||||
| * result might be freed prior to object). */ | |||||
| if (mesh_eval == mesh->runtime.mesh_eval) { | |||||
| object->runtime.is_mesh_eval_owned = false; | |||||
| } | |||||
| else { | |||||
| mesh_eval->id.tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT; | |||||
| object->runtime.is_mesh_eval_owned = true; | |||||
| } | |||||
| /* NOTE: We are not supposed to invoke evaluation for original object, but some areas are still | |||||
| * under process of being ported, so we play safe here. */ | |||||
| if (object->id.tag & LIB_TAG_COPIED_ON_WRITE) { | |||||
| object->data = mesh_eval; | |||||
| } | |||||
| else { | |||||
| /* evaluated will be available via: 'object->runtime.mesh_eval' */ | |||||
| } | |||||
| } | |||||
| static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob) | |||||
| { | { | ||||
| uint32_t eval_flags = DEG_get_eval_flags_for_id(depsgraph, &ob->id); | uint32_t eval_flags = DEG_get_eval_flags_for_id(depsgraph, &ob->id); | ||||
| if (eval_flags & DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY) { | if (eval_flags & DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY) { | ||||
| BKE_shrinkwrap_compute_boundary_data(ob->runtime.mesh_eval); | BKE_shrinkwrap_compute_boundary_data(mesh_eval); | ||||
| } | } | ||||
| } | } | ||||
| static void mesh_runtime_check_normals_valid(const Mesh *mesh) | static void mesh_runtime_check_normals_valid(const Mesh *mesh) | ||||
| { | { | ||||
| UNUSED_VARS_NDEBUG(mesh); | UNUSED_VARS_NDEBUG(mesh); | ||||
| BLI_assert(!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL)); | BLI_assert(!(mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL)); | ||||
| BLI_assert(!(mesh->runtime.cd_dirty_loop & CD_MASK_NORMAL)); | BLI_assert(!(mesh->runtime.cd_dirty_loop & CD_MASK_NORMAL)); | ||||
| Show All 21 Lines | #if 0 /* XXX This is already taken care of in mesh_calc_modifiers()... */ | ||||
| if (need_mapping) { | if (need_mapping) { | ||||
| /* Also add the flag so that it is recorded in lastDataMask. */ | /* Also add the flag so that it is recorded in lastDataMask. */ | ||||
| dataMask->vmask |= CD_MASK_ORIGINDEX; | dataMask->vmask |= CD_MASK_ORIGINDEX; | ||||
| dataMask->emask |= CD_MASK_ORIGINDEX; | dataMask->emask |= CD_MASK_ORIGINDEX; | ||||
| dataMask->pmask |= CD_MASK_ORIGINDEX; | dataMask->pmask |= CD_MASK_ORIGINDEX; | ||||
| } | } | ||||
| #endif | #endif | ||||
| Mesh *mesh_eval = NULL, *mesh_deform_eval = NULL; | |||||
| mesh_calc_modifiers(depsgraph, | mesh_calc_modifiers(depsgraph, | ||||
| scene, | scene, | ||||
| ob, | ob, | ||||
| 1, | 1, | ||||
| need_mapping, | need_mapping, | ||||
| dataMask, | dataMask, | ||||
| -1, | -1, | ||||
| true, | true, | ||||
| true, | true, | ||||
| &ob->runtime.mesh_deform_eval, | &mesh_deform_eval, | ||||
| &ob->runtime.mesh_eval); | &mesh_eval); | ||||
| BKE_object_boundbox_calc_from_mesh(ob, ob->runtime.mesh_eval); | /* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result | ||||
| * is not guaranteed to be owned by object. | |||||
| assign_object_mesh_eval(ob); | * | ||||
| * Check ownership now, since later on we can not go to a mesh owned by someone else via | |||||
| * object's runtime: this could cause access freed data on depsgraph destruction (mesh who owns | |||||
| * the final result might be freed prior to object). */ | |||||
| Mesh *mesh = ob->data; | |||||
| const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime.mesh_eval); | |||||
| BKE_object_eval_assign_data(ob, &mesh_eval->id, is_mesh_eval_owned); | |||||
| ob->runtime.mesh_deform_eval = mesh_deform_eval; | |||||
| ob->runtime.last_data_mask = *dataMask; | ob->runtime.last_data_mask = *dataMask; | ||||
| ob->runtime.last_need_mapping = need_mapping; | ob->runtime.last_need_mapping = need_mapping; | ||||
| BKE_object_boundbox_calc_from_mesh(ob, mesh_eval); | |||||
| if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { | if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { | ||||
| if (DEG_is_active(depsgraph)) { | if (DEG_is_active(depsgraph)) { | ||||
| BKE_sculpt_update_object_after_eval(depsgraph, ob); | BKE_sculpt_update_object_after_eval(depsgraph, ob); | ||||
| } | } | ||||
| } | } | ||||
| if (ob->runtime.mesh_eval != NULL) { | if (mesh_eval != NULL) { | ||||
| mesh_runtime_check_normals_valid(ob->runtime.mesh_eval); | mesh_runtime_check_normals_valid(mesh_eval); | ||||
| } | } | ||||
| mesh_build_extra_data(depsgraph, ob); | mesh_build_extra_data(depsgraph, ob, mesh_eval); | ||||
| } | } | ||||
| static void editbmesh_build_data(struct Depsgraph *depsgraph, | static void editbmesh_build_data(struct Depsgraph *depsgraph, | ||||
| Scene *scene, | Scene *scene, | ||||
| Object *obedit, | Object *obedit, | ||||
| BMEditMesh *em, | BMEditMesh *em, | ||||
| CustomData_MeshMasks *dataMask) | CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph, | ||||
| /* if there's no evaluated mesh or the last data mask used doesn't include | /* if there's no evaluated mesh or the last data mask used doesn't include | ||||
| * the data we need, rebuild the derived mesh | * the data we need, rebuild the derived mesh | ||||
| */ | */ | ||||
| bool need_mapping; | bool need_mapping; | ||||
| CustomData_MeshMasks cddata_masks = *dataMask; | CustomData_MeshMasks cddata_masks = *dataMask; | ||||
| object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); | object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); | ||||
| if (!ob->runtime.mesh_eval || | Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); | ||||
| if ((mesh_eval == NULL) || | |||||
| !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) || | !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) || | ||||
| (need_mapping && !ob->runtime.last_need_mapping)) { | (need_mapping && !ob->runtime.last_need_mapping)) { | ||||
| CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask); | CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask); | ||||
| mesh_build_data( | mesh_build_data( | ||||
| depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime.last_need_mapping); | depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime.last_need_mapping); | ||||
| mesh_eval = BKE_object_get_evaluated_mesh(ob); | |||||
| } | } | ||||
| if (ob->runtime.mesh_eval) { | if (mesh_eval != NULL) { | ||||
| BLI_assert(!(ob->runtime.mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL)); | BLI_assert(!(mesh_eval->runtime.cd_dirty_vert & CD_MASK_NORMAL)); | ||||
| } | } | ||||
| return ob->runtime.mesh_eval; | return mesh_eval; | ||||
| } | } | ||||
| Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, | Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, | ||||
| Scene *scene, | Scene *scene, | ||||
| Object *ob, | Object *ob, | ||||
| const CustomData_MeshMasks *dataMask) | const CustomData_MeshMasks *dataMask) | ||||
| { | { | ||||
| /* This function isn't thread-safe and can't be used during evaluation. */ | /* This function isn't thread-safe and can't be used during evaluation. */ | ||||
| ▲ Show 20 Lines • Show All 466 Lines • Show Last 20 Lines | |||||