Refactoring mesh code, it has become clear that local cleanups and simplifications are limited by the need to keep a C public API for mesh functions. This change makes code more obvious and makes further refactoring much easier. - Add a new `BKE_mesh.hh` header for a C++ only mesh API - Introduce a new `blender::bke::mesh` namespace, documented here: https://wiki.blender.org/wiki/Source/Objects/Mesh#Namespaces - Move some functions to the new namespace, cleaning up their arguments - Move code to `Array` and `float3` where necessary to use the new API - Define existing inline mesh data access functions to the new header - Keep some C API functions where necessary because of RNA - Move all C++ files to use the new header, which includes the old one In the future it may make sense to split up `BKE_mesh.hh` more, but for now keeping the same name as the existing header keeps things simple. Pull Request: blender/blender#105416
169 lines
4.8 KiB
C++
169 lines
4.8 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup modifiers
|
|
*/
|
|
|
|
#include <cstring>
|
|
|
|
#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<float(*)[3]>(
|
|
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,
|
|
};
|