Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/DerivedMesh.cc
| Show First 20 Lines • Show All 655 Lines • ▼ Show 20 Lines | static void mesh_calc_modifiers(struct Depsgraph *depsgraph, | ||||
| const bool use_cache, | const bool use_cache, | ||||
| const bool allow_shared_mesh, | const bool allow_shared_mesh, | ||||
| /* return args */ | /* return args */ | ||||
| Mesh **r_deform, | Mesh **r_deform, | ||||
| Mesh **r_final, | Mesh **r_final, | ||||
| GeometrySet **r_geometry_set) | GeometrySet **r_geometry_set) | ||||
| { | { | ||||
| using namespace blender::bke; | using namespace blender::bke; | ||||
| /* Input and final mesh. Final mesh is only created the moment the first | /* Input mesh shouldn't be modified. */ | ||||
| * constructive modifier is executed, or a deform modifier needs normals | |||||
| * or certain data layers. */ | |||||
| Mesh *mesh_input = (Mesh *)ob->data; | Mesh *mesh_input = (Mesh *)ob->data; | ||||
| /* The final mesh is the result of calculating all enabled modifiers. */ | |||||
| Mesh *mesh_final = nullptr; | Mesh *mesh_final = nullptr; | ||||
| /* The result of calculating all leading deform modifiers. */ | |||||
| Mesh *mesh_deform = nullptr; | Mesh *mesh_deform = nullptr; | ||||
| /* This geometry set contains the non-mesh data that might be generated by modifiers. */ | /* This geometry set contains the non-mesh data that might be generated by modifiers. */ | ||||
| GeometrySet geometry_set_final; | GeometrySet geometry_set_final; | ||||
| BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0); | BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0); | ||||
| /* TODO: Remove use of `deformed_verts` in mesh modifier stack | |||||
| * since mesh positions are now stored in a contiguous array. */ | |||||
| float(*deformed_verts)[3] = nullptr; | |||||
| int num_deformed_verts = mesh_input->totvert; | |||||
| bool isPrevDeform = false; | |||||
| /* Mesh with constructive modifiers but no deformation applied. Tracked | /* Mesh with constructive modifiers but no deformation applied. Tracked | ||||
| * along with final mesh if undeformed / orco coordinates are requested | * along with final mesh if undeformed / orco coordinates are requested | ||||
| * for texturing. */ | * for texturing. */ | ||||
| Mesh *mesh_orco = nullptr; | Mesh *mesh_orco = nullptr; | ||||
| Mesh *mesh_orco_cloth = nullptr; | Mesh *mesh_orco_cloth = nullptr; | ||||
| /* Modifier evaluation modes. */ | /* Modifier evaluation modes. */ | ||||
| const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); | const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); | ||||
| ▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | for (; md; md = md->next, md_datamask = md_datamask->next) { | ||||
| const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); | const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); | ||||
| if (!BKE_modifier_is_enabled(scene, md, required_mode)) { | if (!BKE_modifier_is_enabled(scene, md, required_mode)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) { | if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) { | ||||
| blender::bke::ScopedModifierTimer modifier_timer{*md}; | blender::bke::ScopedModifierTimer modifier_timer{*md}; | ||||
| if (!deformed_verts) { | if (!mesh_final) { | ||||
| deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); | |||||
| } | |||||
| else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { | |||||
| if (mesh_final == nullptr) { | |||||
| mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); | mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); | ||||
| ASSERT_IS_VALID_MESH(mesh_final); | ASSERT_IS_VALID_MESH(mesh_final); | ||||
| } | } | ||||
| BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); | BKE_modifier_deform_verts(md, | ||||
| } | &mectx, | ||||
| mesh_final, | |||||
| BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); | BKE_mesh_vert_positions_for_write(mesh_final), | ||||
| mesh_final->totvert); | |||||
| isPrevDeform = true; | |||||
| } | } | ||||
| else { | else { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| /* Result of all leading deforming modifiers is cached for | /* Result of all leading deforming modifiers is cached for | ||||
| * places that wish to use the original mesh but with deformed | * places that wish to use the original mesh but with deformed | ||||
| * coordinates (like vertex paint). */ | * coordinates (like vertex paint). */ | ||||
| if (r_deform) { | if (r_deform) { | ||||
| mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true); | mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true); | ||||
| if (deformed_verts) { | |||||
| BKE_mesh_vert_coords_apply(mesh_deform, deformed_verts); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| /* Apply all remaining constructive and deforming modifiers. */ | /* Apply all remaining constructive and deforming modifiers. */ | ||||
| bool have_non_onlydeform_modifiers_appled = false; | bool have_non_onlydeform_modifiers_appled = false; | ||||
| for (; md; md = md->next, md_datamask = md_datamask->next) { | for (; md; md = md->next, md_datamask = md_datamask->next) { | ||||
| const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); | const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); | ||||
| ▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | for (; md; md = md->next, md_datamask = md_datamask->next) { | ||||
| if (mesh_final && mesh_orco && mti->requiredDataMask) { | if (mesh_final && mesh_orco && mti->requiredDataMask) { | ||||
| CustomData_MeshMasks mask = {0}; | CustomData_MeshMasks mask = {0}; | ||||
| mti->requiredDataMask(md, &mask); | mti->requiredDataMask(md, &mask); | ||||
| if (mask.vmask & CD_MASK_ORCO) { | if (mask.vmask & CD_MASK_ORCO) { | ||||
| add_orco_mesh(ob, nullptr, mesh_final, mesh_orco, CD_ORCO); | add_orco_mesh(ob, nullptr, mesh_final, mesh_orco, CD_ORCO); | ||||
| } | } | ||||
| } | } | ||||
| /* How to apply modifier depends on (a) what we already have as | |||||
| * a result of previous modifiers (could be a Mesh or just | |||||
| * deformed vertices) and (b) what type the modifier is. */ | |||||
| if (mti->type == eModifierTypeType_OnlyDeform) { | if (mti->type == eModifierTypeType_OnlyDeform) { | ||||
| /* No existing verts to deform, need to build them. */ | if (!mesh_final) { | ||||
| if (!deformed_verts) { | |||||
| if (mesh_final) { | |||||
| /* Deforming a mesh, read the vertex locations | |||||
| * out of the mesh and deform them. Once done with this | |||||
| * run of deformers verts will be written back. */ | |||||
| deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts); | |||||
| } | |||||
| else { | |||||
| deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts); | |||||
| } | |||||
| } | |||||
| /* if this is not the last modifier in the stack then recalculate the normals | |||||
| * to avoid giving bogus normals to the next modifier see: T23673. */ | |||||
| else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) { | |||||
| if (mesh_final == nullptr) { | |||||
| mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); | mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); | ||||
| ASSERT_IS_VALID_MESH(mesh_final); | ASSERT_IS_VALID_MESH(mesh_final); | ||||
| } | } | ||||
| BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); | BKE_modifier_deform_verts(md, | ||||
| } | &mectx, | ||||
| BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); | mesh_final, | ||||
| BKE_mesh_vert_positions_for_write(mesh_final), | |||||
| mesh_final->totvert); | |||||
| } | } | ||||
| else { | else { | ||||
| bool check_for_needs_mapping = false; | bool check_for_needs_mapping = false; | ||||
| /* apply vertex coordinates or build a Mesh as necessary */ | |||||
| if (mesh_final != nullptr) { | if (mesh_final != nullptr) { | ||||
| if (have_non_onlydeform_modifiers_appled == false) { | if (have_non_onlydeform_modifiers_appled == false) { | ||||
| /* If we only deformed, we won't have initialized #CD_ORIGINDEX. | /* If we only deformed, we won't have initialized #CD_ORIGINDEX. | ||||
| * as this is the only part of the function that initializes mapping. */ | * as this is the only part of the function that initializes mapping. */ | ||||
| check_for_needs_mapping = true; | check_for_needs_mapping = true; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); | mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); | ||||
| ASSERT_IS_VALID_MESH(mesh_final); | ASSERT_IS_VALID_MESH(mesh_final); | ||||
| check_for_needs_mapping = true; | check_for_needs_mapping = true; | ||||
| } | } | ||||
| if (deformed_verts) { | |||||
| BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); | |||||
| } | |||||
| have_non_onlydeform_modifiers_appled = true; | have_non_onlydeform_modifiers_appled = true; | ||||
| /* determine which data layers are needed by following modifiers */ | /* determine which data layers are needed by following modifiers */ | ||||
| CustomData_MeshMasks nextmask = md_datamask->next ? md_datamask->next->mask : final_datamask; | CustomData_MeshMasks nextmask = md_datamask->next ? md_datamask->next->mask : final_datamask; | ||||
| if (check_for_needs_mapping) { | if (check_for_needs_mapping) { | ||||
| /* Initialize original indices the first time we evaluate a | /* Initialize original indices the first time we evaluate a | ||||
| * constructive modifier. Modifiers will then do mapping mostly | * constructive modifier. Modifiers will then do mapping mostly | ||||
| ▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | else { | ||||
| if (mesh_next) { | if (mesh_next) { | ||||
| /* if the modifier returned a new mesh, release the old one */ | /* if the modifier returned a new mesh, release the old one */ | ||||
| if (mesh_final != mesh_next) { | if (mesh_final != mesh_next) { | ||||
| BLI_assert(mesh_final != mesh_input); | BLI_assert(mesh_final != mesh_input); | ||||
| BKE_id_free(nullptr, mesh_final); | BKE_id_free(nullptr, mesh_final); | ||||
| } | } | ||||
| mesh_final = mesh_next; | mesh_final = mesh_next; | ||||
| if (deformed_verts) { | |||||
| MEM_freeN(deformed_verts); | |||||
| deformed_verts = nullptr; | |||||
| } | |||||
| } | } | ||||
| /* create an orco mesh in parallel */ | /* create an orco mesh in parallel */ | ||||
| if (nextmask.vmask & CD_MASK_ORCO) { | if (nextmask.vmask & CD_MASK_ORCO) { | ||||
| if (!mesh_orco) { | if (!mesh_orco) { | ||||
| mesh_orco = create_orco_mesh(ob, mesh_input, nullptr, CD_ORCO); | mesh_orco = create_orco_mesh(ob, mesh_input, nullptr, CD_ORCO); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | else { | ||||
| /* XXX Temp and hackish solution! */ | /* XXX Temp and hackish solution! */ | ||||
| if (md->type == eModifierType_DynamicPaint) { | if (md->type == eModifierType_DynamicPaint) { | ||||
| append_mask.lmask |= CD_MASK_PREVIEW_MLOOPCOL; | append_mask.lmask |= CD_MASK_PREVIEW_MLOOPCOL; | ||||
| } | } | ||||
| mesh_final->runtime->deformed_only = false; | mesh_final->runtime->deformed_only = false; | ||||
| } | } | ||||
| isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform); | |||||
| if (sculpt_mode && md->type == eModifierType_Multires) { | if (sculpt_mode && md->type == eModifierType_Multires) { | ||||
| multires_applied = true; | multires_applied = true; | ||||
| } | } | ||||
| } | } | ||||
| BLI_linklist_free((LinkNode *)datamasks, nullptr); | BLI_linklist_free((LinkNode *)datamasks, nullptr); | ||||
| for (md = firstmd; md; md = md->next) { | for (md = firstmd; md; md = md->next) { | ||||
| BKE_modifier_free_temporary_data(md); | BKE_modifier_free_temporary_data(md); | ||||
| } | } | ||||
| /* Yay, we are done. If we have a Mesh and deformed vertices, | |||||
| * we need to apply these back onto the Mesh. If we have no | |||||
| * Mesh then we need to build one. */ | |||||
| if (mesh_final == nullptr) { | if (mesh_final == nullptr) { | ||||
| if (deformed_verts == nullptr && allow_shared_mesh) { | if (allow_shared_mesh) { | ||||
| mesh_final = mesh_input; | mesh_final = mesh_input; | ||||
| } | } | ||||
| else { | else { | ||||
| mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); | mesh_final = BKE_mesh_copy_for_eval(mesh_input, true); | ||||
| } | } | ||||
| } | } | ||||
| if (deformed_verts) { | |||||
| BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); | |||||
| MEM_freeN(deformed_verts); | |||||
| deformed_verts = nullptr; | |||||
| } | |||||
| /* Denotes whether the object which the modifier stack came from owns the mesh or whether the | /* Denotes whether the object which the modifier stack came from owns the mesh or whether the | ||||
| * mesh is shared across multiple objects since there are no effective modifiers. */ | * mesh is shared across multiple objects since there are no effective modifiers. */ | ||||
| const bool is_own_mesh = (mesh_final != mesh_input); | const bool is_own_mesh = (mesh_final != mesh_input); | ||||
| /* Add orco coordinates to final and deformed mesh if requested. */ | /* Add orco coordinates to final and deformed mesh if requested. */ | ||||
| if (final_datamask.vmask & CD_MASK_ORCO) { | if (final_datamask.vmask & CD_MASK_ORCO) { | ||||
| /* No need in ORCO layer if the mesh was not deformed or modified: undeformed mesh in this case | /* No need in ORCO layer if the mesh was not deformed or modified: undeformed mesh in this case | ||||
| ▲ Show 20 Lines • Show All 919 Lines • Show Last 20 Lines | |||||