/* SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup modifiers */ #include #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" #include "BLT_translation.h" #include "DNA_defaults.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" #include "BKE_context.h" #include "BKE_mesh.hh" #include "BKE_modifier.h" #include "BKE_screen.h" #include "UI_interface.h" #include "UI_resources.h" #include "RNA_access.h" #include "RNA_prototypes.h" #include "bmesh.h" #include "bmesh_tools.h" #include "MOD_modifiertypes.h" #include "MOD_ui_common.h" static Mesh *triangulate_mesh(Mesh *mesh, const int quad_method, const int ngon_method, const int min_vertices, const int flag) { Mesh *result; BMesh *bm; CustomData_MeshMasks cd_mask_extra{}; cd_mask_extra.vmask = CD_MASK_ORIGINDEX; cd_mask_extra.emask = CD_MASK_ORIGINDEX; cd_mask_extra.pmask = CD_MASK_ORIGINDEX; bool keep_clnors = (flag & MOD_TRIANGULATE_KEEP_CUSTOMLOOP_NORMALS) != 0; if (keep_clnors) { BKE_mesh_calc_normals_split(mesh); /* We need that one to 'survive' to/from BMesh conversions. */ CustomData_clear_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); cd_mask_extra.lmask |= CD_MASK_NORMAL; } BMeshCreateParams bmesh_create_params{}; BMeshFromMeshParams bmesh_from_mesh_params{}; bmesh_from_mesh_params.calc_face_normal = true; bmesh_from_mesh_params.calc_vert_normal = false; bmesh_from_mesh_params.cd_mask_extra = cd_mask_extra; bm = BKE_mesh_to_bmesh_ex(mesh, &bmesh_create_params, &bmesh_from_mesh_params); BM_mesh_triangulate( bm, quad_method, ngon_method, min_vertices, false, nullptr, nullptr, nullptr); result = BKE_mesh_from_bmesh_for_eval_nomain(bm, &cd_mask_extra, mesh); BM_mesh_free(bm); if (keep_clnors) { float(*lnors)[3] = static_cast( CustomData_get_layer_for_write(&result->ldata, CD_NORMAL, result->totloop)); BLI_assert(lnors != nullptr); BKE_mesh_set_custom_normals(result, lnors); /* Do some cleanup, we do not want those temp data to stay around. */ CustomData_set_layer_flag(&mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); CustomData_set_layer_flag(&result->ldata, CD_NORMAL, CD_FLAG_TEMPORARY); } return result; } static void initData(ModifierData *md) { TriangulateModifierData *tmd = (TriangulateModifierData *)md; BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(tmd, modifier)); MEMCPY_STRUCT_AFTER(tmd, DNA_struct_default_get(TriangulateModifierData), modifier); /* Enable in editmode by default */ md->mode |= eModifierMode_Editmode; } static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext * /*ctx*/, Mesh *mesh) { TriangulateModifierData *tmd = (TriangulateModifierData *)md; Mesh *result; if (!(result = triangulate_mesh( mesh, tmd->quad_method, tmd->ngon_method, tmd->min_vertices, tmd->flag))) { return mesh; } return result; } static void panel_draw(const bContext * /*C*/, Panel *panel) { uiLayout *layout = panel->layout; PointerRNA ob_ptr; PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr); uiLayoutSetPropSep(layout, true); uiItemR(layout, ptr, "quad_method", 0, nullptr, ICON_NONE); uiItemR(layout, ptr, "ngon_method", 0, nullptr, ICON_NONE); uiItemR(layout, ptr, "min_vertices", 0, nullptr, ICON_NONE); uiItemR(layout, ptr, "keep_custom_normals", 0, nullptr, ICON_NONE); modifier_panel_end(layout, ptr); } static void panelRegister(ARegionType *region_type) { modifier_panel_register(region_type, eModifierType_Triangulate, panel_draw); } ModifierTypeInfo modifierType_Triangulate = { /*name*/ N_("Triangulate"), /*structName*/ "TriangulateModifierData", /*structSize*/ sizeof(TriangulateModifierData), /*srna*/ &RNA_TriangulateModifier, /*type*/ eModifierTypeType_Constructive, /*flags*/ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, /*icon*/ ICON_MOD_TRIANGULATE, /*copyData*/ BKE_modifier_copydata_generic, /*deformVerts*/ nullptr, /*deformMatrices*/ nullptr, /*deformVertsEM*/ nullptr, /*deformMatricesEM*/ nullptr, /*modifyMesh*/ modifyMesh, /*modifyGeometrySet*/ nullptr, /*initData*/ initData, /*requiredDataMask*/ nullptr, // requiredDataMask, /*freeData*/ nullptr, /*isDisabled*/ nullptr, /*updateDepsgraph*/ nullptr, /*dependsOnTime*/ nullptr, /*dependsOnNormals*/ nullptr, /*foreachIDLink*/ nullptr, /*foreachTexLink*/ nullptr, /*freeRuntimeData*/ nullptr, /*panelRegister*/ panelRegister, /*blendWrite*/ nullptr, /*blendRead*/ nullptr, };