Mesh: Move runtime data out of DNA

This commit replaces the `Mesh_Runtime` struct embedded in `Mesh`
with `blender::bke::MeshRuntime`. This has quite a few benefits:
- It's possible to use C++ types like `std::mutex`, `Array`,
  `BitVector`, etc. more easily
- Meshes saved in files are slightly smaller
- Copying and writing meshes is a bit more obvious without
  clearing of runtime data, etc.

The first is by far the most important. It will allows us to avoid a
bunch of manual memory management boilerplate that is error-prone and
annoying. It should also simplify future CoW improvements for runtime
data.

This patch doesn't change anything besides changing `mesh.runtime.data`
to `mesh.runtime->data`. The cleanups above will happen separately.

Differential Revision: https://developer.blender.org/D16180
This commit is contained in:
Hans Goudey 2022-10-12 20:55:26 -05:00
parent b3e6a2888a
commit c34c6d3e25
74 changed files with 578 additions and 508 deletions

View File

@ -11,15 +11,25 @@ extern "C" {
#endif
struct BMEditMesh;
struct EditMeshData;
void BKE_editmesh_cache_ensure_poly_normals(struct BMEditMesh *em, struct EditMeshData *emd);
void BKE_editmesh_cache_ensure_vert_normals(struct BMEditMesh *em, struct EditMeshData *emd);
typedef struct EditMeshData {
/** when set, \a vertexNos, polyNos are lazy initialized */
const float (*vertexCos)[3];
void BKE_editmesh_cache_ensure_poly_centers(struct BMEditMesh *em, struct EditMeshData *emd);
/** lazy initialize (when \a vertexCos is set) */
float const (*vertexNos)[3];
float const (*polyNos)[3];
/** also lazy init but don't depend on \a vertexCos */
const float (*polyCos)[3];
} EditMeshData;
void BKE_editmesh_cache_ensure_poly_normals(struct BMEditMesh *em, EditMeshData *emd);
void BKE_editmesh_cache_ensure_vert_normals(struct BMEditMesh *em, EditMeshData *emd);
void BKE_editmesh_cache_ensure_poly_centers(struct BMEditMesh *em, EditMeshData *emd);
bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em,
struct EditMeshData *emd,
EditMeshData *emd,
float min[3],
float max[3]);

View File

@ -9,6 +9,7 @@
*/
//#include "BKE_customdata.h" /* for eCustomDataMask */
#include "BKE_mesh_types.h"
#ifdef __cplusplus
extern "C" {
@ -25,22 +26,11 @@ struct Mesh;
struct Object;
struct Scene;
/**
* \brief Initialize the runtime of the given mesh.
*
* Function expects that the runtime is already cleared.
*/
void BKE_mesh_runtime_init_data(struct Mesh *mesh);
/**
* \brief Free all data (and mutexes) inside the runtime of the given mesh.
*/
void BKE_mesh_runtime_free_data(struct Mesh *mesh);
/**
* Clear all pointers which we don't want to be shared on copying the datablock.
* However, keep all the flags which defines what the mesh is (for example, that
* it's deformed only, or that its custom data layers are out of date.)
*/
void BKE_mesh_runtime_reset_on_copy(struct Mesh *mesh, int flag);
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh);
void BKE_mesh_runtime_looptri_recalc(struct Mesh *mesh);
/**
@ -66,6 +56,11 @@ void BKE_mesh_runtime_verttri_from_looptri(struct MVertTri *r_verttri,
const struct MLoopTri *looptri,
int looptri_num);
/** \note Only used for access in C. */
bool BKE_mesh_is_deformed_only(const struct Mesh *mesh);
/** \note Only used for access in C. */
eMeshWrapperType BKE_mesh_wrapper_type(const struct Mesh *mesh);
/* NOTE: the functions below are defined in DerivedMesh.cc, and are intended to be moved
* to a more suitable location when that file is removed.
* They should also be renamed to use conventions from BKE, not old DerivedMesh.cc.

View File

@ -1,11 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2020 Blender Foundation. All rights reserved. */
#pragma once
/** \file
* \ingroup bke
*/
#ifdef __cplusplus
# include "BLI_span.hh"
# include "DNA_customdata_types.h"
# include "MEM_guardedalloc.h"
struct BVHCache;
struct EditMeshData;
struct MLoopTri;
struct ShrinkwrapBoundaryData;
struct SubdivCCG;
struct SubsurfRuntimeData;
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef enum eMeshBatchDirtyMode {
BKE_MESH_BATCH_DIRTY_ALL = 0,
BKE_MESH_BATCH_DIRTY_SELECT,
@ -14,3 +36,125 @@ typedef enum eMeshBatchDirtyMode {
BKE_MESH_BATCH_DIRTY_UVEDIT_ALL,
BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT,
} eMeshBatchDirtyMode;
/** #MeshRuntime.wrapper_type */
typedef enum eMeshWrapperType {
/** Use mesh data (#Mesh.mvert, #Mesh.medge, #Mesh.mloop, #Mesh.mpoly). */
ME_WRAPPER_TYPE_MDATA = 0,
/** Use edit-mesh data (#Mesh.edit_mesh, #MeshRuntime.edit_data). */
ME_WRAPPER_TYPE_BMESH = 1,
/** Use subdivision mesh data (#MeshRuntime.mesh_eval). */
ME_WRAPPER_TYPE_SUBD = 2,
} eMeshWrapperType;
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
namespace blender::bke {
/**
* \warning Typical access is done via #Mesh::looptris().
*/
struct MLoopTri_Store {
/* WARNING! swapping between array (ready-to-be-used data) and array_wip
* (where data is actually computed)
* shall always be protected by same lock as one used for looptris computing. */
MLoopTri *array = nullptr;
MLoopTri *array_wip = nullptr;
int len = 0;
int len_alloc = 0;
};
struct MeshRuntime {
/* Evaluated mesh for objects which do not have effective modifiers.
* This mesh is used as a result of modifier stack evaluation.
* Since modifier stack evaluation is threaded on object level we need some synchronization. */
Mesh *mesh_eval = nullptr;
void *eval_mutex = nullptr;
/* A separate mutex is needed for normal calculation, because sometimes
* the normals are needed while #eval_mutex is already locked. */
void *normals_mutex = nullptr;
/** Needed to ensure some thread-safety during render data pre-processing. */
void *render_mutex = nullptr;
/** Lazily initialized SoA data from the #edit_mesh field in #Mesh. */
EditMeshData *edit_data = nullptr;
/**
* Data used to efficiently draw the mesh in the viewport, especially useful when
* the same mesh is used in many objects or instances. See `draw_cache_impl_mesh.cc`.
*/
void *batch_cache = nullptr;
/** Cache for derived triangulation of the mesh. */
MLoopTri_Store looptris;
/** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */
BVHCache *bvh_cache = nullptr;
/** Cache of non-manifold boundary data for Shrinkwrap Target Project. */
ShrinkwrapBoundaryData *shrinkwrap_data = nullptr;
/** Needed in case we need to lazily initialize the mesh. */
CustomData_MeshMasks cd_mask_extra = {};
SubdivCCG *subdiv_ccg = nullptr;
int subdiv_ccg_tot_level = 0;
/** Set by modifier stack if only deformed from original. */
bool deformed_only = false;
/**
* Copied from edit-mesh (hint, draw with edit-mesh data when true).
*
* Modifiers that edit the mesh data in-place must set this to false
* (most #eModifierTypeType_NonGeometrical modifiers). Otherwise the edit-mesh
* data will be used for drawing, missing changes from modifiers. See T79517.
*/
bool is_original_bmesh = false;
/** #eMeshWrapperType and others. */
eMeshWrapperType wrapper_type = ME_WRAPPER_TYPE_MDATA;
/**
* A type mask from wrapper_type,
* in case there are differences in finalizing logic between types.
*/
eMeshWrapperType wrapper_type_finalize = ME_WRAPPER_TYPE_MDATA;
/**
* Settings for lazily evaluating the subdivision on the CPU if needed. These are
* set in the modifier when GPU subdivision can be performed, and owned by the by
* the modifier in the object.
*/
SubsurfRuntimeData *subsurf_runtime_data = nullptr;
/**
* Caches for lazily computed vertex and polygon normals. These are stored here rather than in
* #CustomData because they can be calculated on a const mesh, and adding custom data layers on a
* const mesh is not thread-safe.
*/
bool vert_normals_dirty = false;
bool poly_normals_dirty = false;
float (*vert_normals)[3] = nullptr;
float (*poly_normals)[3] = nullptr;
/**
* A #BLI_bitmap containing tags for the center vertices of subdivided polygons, set by the
* subdivision surface modifier and used by drawing code instead of polygon center face dots.
*/
uint32_t *subsurf_face_dot_tags = nullptr;
MeshRuntime();
/** \warning This does not free all data currently. See #BKE_mesh_runtime_free_data. */
~MeshRuntime();
MEM_CXX_CLASS_ALLOC_FUNCS("MeshRuntime")
};
} // namespace blender::bke
#endif

View File

@ -35,6 +35,7 @@
#include "BKE_colorband.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_geometry_set.hh"
#include "BKE_geometry_set_instances.hh"
#include "BKE_key.h"
@ -537,7 +538,7 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
(final_datamask->lmask & CD_MASK_NORMAL) != 0);
/* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */
SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime.subsurf_runtime_data;
SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data;
if (subsurf_runtime_data) {
subsurf_runtime_data->calc_loop_normals = calc_loop_normals;
}
@ -585,11 +586,12 @@ static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval)
void BKE_mesh_wrapper_deferred_finalize_mdata(Mesh *me_eval,
const CustomData_MeshMasks *cd_mask_finalize)
{
if (me_eval->runtime.wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) {
if (me_eval->runtime->wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) {
editbmesh_calc_modifier_final_normals(me_eval, cd_mask_finalize);
me_eval->runtime.wrapper_type_finalize &= ~(1 << ME_WRAPPER_TYPE_BMESH);
me_eval->runtime->wrapper_type_finalize = eMeshWrapperType(
me_eval->runtime->wrapper_type_finalize & ~(1 << ME_WRAPPER_TYPE_BMESH));
}
BLI_assert(me_eval->runtime.wrapper_type_finalize == 0);
BLI_assert(me_eval->runtime->wrapper_type_finalize == 0);
}
/**
@ -1052,7 +1054,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
append_mask.lmask |= CD_MASK_PREVIEW_MLOOPCOL;
}
mesh_final->runtime.deformed_only = false;
mesh_final->runtime->deformed_only = false;
}
isPrevDeform = (mti->type == eModifierTypeType_OnlyDeform);
@ -1119,7 +1121,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
mesh_calc_finalize(mesh_input, mesh_final);
}
else {
Mesh_Runtime *runtime = &mesh_input->runtime;
blender::bke::MeshRuntime *runtime = mesh_input->runtime;
if (runtime->mesh_eval == nullptr) {
BLI_assert(runtime->eval_mutex != nullptr);
BLI_mutex_lock((ThreadMutex *)runtime->eval_mutex);
@ -1207,7 +1209,7 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
const bool calc_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 ||
(final_datamask->lmask & CD_MASK_NORMAL) != 0);
SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime.subsurf_runtime_data;
SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime->subsurf_runtime_data;
if (subsurf_runtime_data) {
subsurf_runtime_data->calc_loop_normals = calc_loop_normals;
}
@ -1234,9 +1236,10 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
static void editbmesh_calc_modifier_final_normals_or_defer(
Mesh *mesh_final, const CustomData_MeshMasks *final_datamask)
{
if (mesh_final->runtime.wrapper_type != ME_WRAPPER_TYPE_MDATA) {
if (mesh_final->runtime->wrapper_type != ME_WRAPPER_TYPE_MDATA) {
/* Generated at draw time. */
mesh_final->runtime.wrapper_type_finalize = (1 << mesh_final->runtime.wrapper_type);
mesh_final->runtime->wrapper_type_finalize = eMeshWrapperType(
1 << mesh_final->runtime->wrapper_type);
return;
}
@ -1450,7 +1453,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
deformed_verts = nullptr;
}
}
mesh_final->runtime.deformed_only = false;
mesh_final->runtime->deformed_only = false;
}
if (r_cage && i == cageIndex) {
@ -1469,7 +1472,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
if (!BKE_mesh_runtime_ensure_edit_data(me_orig)) {
BKE_mesh_runtime_reset_edit_data(me_orig);
}
me_orig->runtime.edit_data->vertexCos = (const float(*)[3])MEM_dupallocN(deformed_verts);
me_orig->runtime->edit_data->vertexCos = (const float(*)[3])MEM_dupallocN(
deformed_verts);
}
mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords(
em_input,
@ -1583,7 +1587,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph,
* 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 = (Mesh *)ob->data;
const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime.mesh_eval);
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);
/* Add the final mesh as a non-owning component to the geometry set. */
@ -1643,7 +1647,7 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph,
}
}
const bool is_mesh_eval_owned = (me_final != mesh->runtime.mesh_eval);
const bool is_mesh_eval_owned = (me_final != mesh->runtime->mesh_eval);
BKE_object_eval_assign_data(obedit, &me_final->id, is_mesh_eval_owned);
obedit->runtime.editmesh_eval_cage = me_cage;
@ -1914,7 +1918,7 @@ static void make_vertexcos__mapFunc(void *userData,
void mesh_get_mapped_verts_coords(Mesh *me_eval, float (*r_cos)[3], const int totcos)
{
if (me_eval->runtime.deformed_only == false) {
if (me_eval->runtime->deformed_only == false) {
MappedUserData userData;
memset(r_cos, 0, sizeof(*r_cos) * totcos);
userData.vertexcos = r_cos;

View File

@ -1222,8 +1222,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
const BVHCacheType bvh_cache_type,
const int tree_type)
{
BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime.bvh_cache;
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime->bvh_cache;
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime->eval_mutex;
const MLoopTri *looptri = nullptr;
int looptri_len = 0;

View File

@ -826,7 +826,7 @@ static void cloth_from_mesh(ClothModifierData *clmd, const Object *ob, Mesh *mes
const MLoop *mloop = BKE_mesh_loops(mesh);
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh);
const uint mvert_num = mesh->totvert;
const uint looptri_num = mesh->runtime.looptris.len;
const uint looptri_num = BKE_mesh_runtime_looptri_len(mesh);
/* Allocate our vertices. */
clmd->clothObject->mvert_num = mvert_num;

View File

@ -240,12 +240,12 @@ const float (*BKE_editmesh_vert_coords_when_deformed(Depsgraph *depsgraph,
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object_eval);
if ((me->runtime.edit_data != nullptr) && (me->runtime.edit_data->vertexCos != nullptr)) {
if ((me->runtime->edit_data != nullptr) && (me->runtime->edit_data->vertexCos != nullptr)) {
/* Deformed, and we have deformed coords already. */
coords = me->runtime.edit_data->vertexCos;
coords = me->runtime->edit_data->vertexCos;
}
else if ((editmesh_eval_final != nullptr) &&
(editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
(editmesh_eval_final->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
/* If this is an edit-mesh type, leave nullptr as we can use the vertex coords. */
}
else {

View File

@ -1498,7 +1498,7 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
for (int i = 0; i < mesh->totvert; i++) {
normalize_v3(process.no[i]);
}
mesh->runtime.vert_normals = process.no;
mesh->runtime->vert_normals = process.no;
BKE_mesh_vertex_normals_clear_dirty(mesh);
mesh->totloop = loop_offset;

View File

@ -89,7 +89,7 @@ static void mesh_init_data(ID *id)
CustomData_reset(&mesh->pdata);
CustomData_reset(&mesh->ldata);
BKE_mesh_runtime_init_data(mesh);
mesh->runtime = new blender::bke::MeshRuntime();
/* A newly created mesh does not have normals, so tag them dirty. This will be cleared
* by #BKE_mesh_vertex_normals_clear_dirty or #BKE_mesh_poly_normals_ensure. */
@ -103,14 +103,19 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
Mesh *mesh_dst = (Mesh *)id_dst;
const Mesh *mesh_src = (const Mesh *)id_src;
BKE_mesh_runtime_reset_on_copy(mesh_dst, flag);
mesh_dst->runtime = new blender::bke::MeshRuntime();
mesh_dst->runtime->deformed_only = mesh_src->runtime->deformed_only;
mesh_dst->runtime->wrapper_type = mesh_src->runtime->wrapper_type;
mesh_dst->runtime->wrapper_type_finalize = mesh_src->runtime->wrapper_type_finalize;
mesh_dst->runtime->subsurf_runtime_data = mesh_src->runtime->subsurf_runtime_data;
mesh_dst->runtime->cd_mask_extra = mesh_src->runtime->cd_mask_extra;
/* Copy face dot tags, since meshes may be duplicated after a subsurf modifier
* or node, but we still need to be able to draw face center vertices. */
mesh_dst->runtime.subsurf_face_dot_tags = static_cast<uint32_t *>(
MEM_dupallocN(mesh_src->runtime.subsurf_face_dot_tags));
mesh_dst->runtime->subsurf_face_dot_tags = static_cast<uint32_t *>(
MEM_dupallocN(mesh_src->runtime->subsurf_face_dot_tags));
if ((mesh_src->id.tag & LIB_TAG_NO_MAIN) == 0) {
/* This is a direct copy of a main mesh, so for now it has the same topology. */
mesh_dst->runtime.deformed_only = true;
mesh_dst->runtime->deformed_only = true;
}
/* This option is set for run-time meshes that have been copied from the current objects mode.
* Currently this is used for edit-mesh although it could be used for sculpt or other
@ -121,7 +126,7 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
*
* While this could be the callers responsibility, keep here since it's
* highly unlikely we want to create a duplicate and not use it for drawing. */
mesh_dst->runtime.is_original_bmesh = false;
mesh_dst->runtime->is_original_bmesh = false;
/* Only do tessface if we have no polys. */
const bool do_tessface = ((mesh_src->totface != 0) && (mesh_src->totpoly == 0));
@ -194,6 +199,8 @@ static void mesh_free_data(ID *id)
BKE_mesh_runtime_free_data(mesh);
mesh_clear_geometry(mesh);
MEM_SAFE_FREE(mesh->mat);
delete mesh->runtime;
}
static void mesh_foreach_id(ID *id, LibraryForeachIDData *data)
@ -229,7 +236,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
mesh->mface = nullptr;
mesh->totface = 0;
memset(&mesh->fdata, 0, sizeof(mesh->fdata));
mesh->runtime = blender::dna::shallow_zero_initialize();
mesh->runtime = nullptr;
/* Do not store actual geometry data in case this is a library override ID. */
if (ID_IS_OVERRIDE_LIBRARY(mesh) && !is_undo) {
@ -339,8 +346,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
mesh->texflag &= ~ME_AUTOSPACE_EVALUATED;
mesh->edit_mesh = nullptr;
mesh->runtime = blender::dna::shallow_zero_initialize();
BKE_mesh_runtime_init_data(mesh);
mesh->runtime = new blender::bke::MeshRuntime();
/* happens with old files */
if (mesh->mselect == nullptr) {
@ -1137,7 +1143,7 @@ static void ensure_orig_index_layer(CustomData &data, const int size)
void BKE_mesh_ensure_default_orig_index_customdata(Mesh *mesh)
{
BLI_assert(mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA);
BLI_assert(mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_MDATA);
BKE_mesh_ensure_default_orig_index_customdata_no_check(mesh);
}
@ -2106,8 +2112,8 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
}
/* Update normals manually to avoid recalculation after this operation. */
mesh->runtime.vert_normals = (float(*)[3])MEM_reallocN(mesh->runtime.vert_normals,
sizeof(float[3]) * mesh->totvert);
mesh->runtime->vert_normals = (float(*)[3])MEM_reallocN(mesh->runtime->vert_normals,
sizeof(float[3]) * mesh->totvert);
/* Perform actual split of vertices and edges. */
split_faces_split_new_verts(mesh, new_verts, num_new_verts);
@ -2141,10 +2147,10 @@ void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh)
/* We are here because something did change in the mesh. This means we can not trust the existing
* evaluated mesh, and we don't know what parts of the mesh did change. So we simply delete the
* evaluated mesh and let objects to re-create it with updated settings. */
if (mesh->runtime.mesh_eval != nullptr) {
mesh->runtime.mesh_eval->edit_mesh = nullptr;
BKE_id_free(nullptr, mesh->runtime.mesh_eval);
mesh->runtime.mesh_eval = nullptr;
if (mesh->runtime->mesh_eval != nullptr) {
mesh->runtime->mesh_eval->edit_mesh = nullptr;
BKE_id_free(nullptr, mesh->runtime->mesh_eval);
mesh->runtime->mesh_eval = nullptr;
}
if (DEG_is_active(depsgraph)) {
Mesh *mesh_orig = (Mesh *)DEG_get_original_id(&mesh->id);

View File

@ -903,7 +903,7 @@ static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh)
{
/* While we could copy this into the new mesh,
* add the data to 'mesh' so future calls to this function don't need to re-convert the data. */
if (mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
if (mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
BKE_mesh_wrapper_ensure_mdata(mesh);
}
else {

View File

@ -41,9 +41,9 @@ char *BKE_mesh_debug_info(const Mesh *me)
BLI_dynstr_appendf(dynstr, " 'totface': %d,\n", me->totface);
BLI_dynstr_appendf(dynstr, " 'totpoly': %d,\n", me->totpoly);
BLI_dynstr_appendf(dynstr, " 'runtime.deformed_only': %d,\n", me->runtime.deformed_only);
BLI_dynstr_appendf(dynstr, " 'runtime.deformed_only': %d,\n", me->runtime->deformed_only);
BLI_dynstr_appendf(
dynstr, " 'runtime.is_original_bmesh': %d,\n", me->runtime.is_original_bmesh);
dynstr, " 'runtime->is_original_bmesh': %d,\n", me->runtime->is_original_bmesh);
BLI_dynstr_append(dynstr, " 'vert_layers': (\n");
CustomData_debug_info_from_layers(&me->vdata, indent8, dynstr);

View File

@ -36,18 +36,18 @@ void BKE_mesh_foreach_mapped_vert(
void *userData,
MeshForeachFlag flag)
{
if (mesh->edit_mesh != nullptr && mesh->runtime.edit_data != nullptr) {
if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data != nullptr) {
BMEditMesh *em = mesh->edit_mesh;
BMesh *bm = em->bm;
BMIter iter;
BMVert *eve;
int i;
if (mesh->runtime.edit_data->vertexCos != nullptr) {
const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
if (mesh->runtime->edit_data->vertexCos != nullptr) {
const float(*vertexCos)[3] = mesh->runtime->edit_data->vertexCos;
const float(*vertexNos)[3];
if (flag & MESH_FOREACH_USE_NORMAL) {
BKE_editmesh_cache_ensure_vert_normals(em, mesh->runtime.edit_data);
vertexNos = mesh->runtime.edit_data->vertexNos;
BKE_editmesh_cache_ensure_vert_normals(em, mesh->runtime->edit_data);
vertexNos = mesh->runtime->edit_data->vertexNos;
}
else {
vertexNos = nullptr;
@ -96,14 +96,14 @@ void BKE_mesh_foreach_mapped_edge(
void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
void *userData)
{
if (mesh->edit_mesh != nullptr && mesh->runtime.edit_data) {
if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data) {
BMEditMesh *em = mesh->edit_mesh;
BMesh *bm = em->bm;
BMIter iter;
BMEdge *eed;
int i;
if (mesh->runtime.edit_data->vertexCos != nullptr) {
const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
if (mesh->runtime->edit_data->vertexCos != nullptr) {
const float(*vertexCos)[3] = mesh->runtime->edit_data->vertexCos;
BM_mesh_elem_index_ensure(bm, BM_VERT);
BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) {
@ -154,13 +154,13 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh,
/* We can't use `dm->getLoopDataLayout(dm)` here,
* we want to always access `dm->loopData`, `EditDerivedBMesh` would
* return loop data from BMesh itself. */
if (mesh->edit_mesh != nullptr && mesh->runtime.edit_data) {
if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data) {
BMEditMesh *em = mesh->edit_mesh;
BMesh *bm = em->bm;
BMIter iter;
BMFace *efa;
const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos;
const float(*vertexCos)[3] = mesh->runtime->edit_data->vertexCos;
/* XXX: investigate using EditMesh data. */
const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ?
@ -231,7 +231,7 @@ void BKE_mesh_foreach_mapped_face_center(
void *userData,
MeshForeachFlag flag)
{
if (mesh->edit_mesh != nullptr && mesh->runtime.edit_data != nullptr) {
if (mesh->edit_mesh != nullptr && mesh->runtime->edit_data != nullptr) {
BMEditMesh *em = mesh->edit_mesh;
BMesh *bm = em->bm;
const float(*polyCos)[3];
@ -240,12 +240,12 @@ void BKE_mesh_foreach_mapped_face_center(
BMIter iter;
int i;
BKE_editmesh_cache_ensure_poly_centers(em, mesh->runtime.edit_data);
polyCos = mesh->runtime.edit_data->polyCos; /* always set */
BKE_editmesh_cache_ensure_poly_centers(em, mesh->runtime->edit_data);
polyCos = mesh->runtime->edit_data->polyCos; /* always set */
if (flag & MESH_FOREACH_USE_NORMAL) {
BKE_editmesh_cache_ensure_poly_normals(em, mesh->runtime.edit_data);
polyNos = mesh->runtime.edit_data->polyNos; /* maybe nullptr */
BKE_editmesh_cache_ensure_poly_normals(em, mesh->runtime->edit_data);
polyNos = mesh->runtime->edit_data->polyNos; /* maybe nullptr */
}
else {
polyNos = nullptr;
@ -317,7 +317,7 @@ void BKE_mesh_foreach_mapped_subdiv_face_center(
BKE_mesh_vertex_normals_ensure(mesh) :
nullptr;
const int *index = static_cast<const int *>(CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX));
const BLI_bitmap *facedot_tags = mesh->runtime.subsurf_face_dot_tags;
const BLI_bitmap *facedot_tags = mesh->runtime->subsurf_face_dot_tags;
BLI_assert(facedot_tags != nullptr);
if (index) {

View File

@ -95,72 +95,72 @@ static void add_v3_v3_atomic(float r[3], const float a[3])
void BKE_mesh_normals_tag_dirty(Mesh *mesh)
{
mesh->runtime.vert_normals_dirty = true;
mesh->runtime.poly_normals_dirty = true;
mesh->runtime->vert_normals_dirty = true;
mesh->runtime->poly_normals_dirty = true;
}
float (*BKE_mesh_vertex_normals_for_write(Mesh *mesh))[3]
{
if (mesh->runtime.vert_normals == nullptr) {
mesh->runtime.vert_normals = (float(*)[3])MEM_malloc_arrayN(
if (mesh->runtime->vert_normals == nullptr) {
mesh->runtime->vert_normals = (float(*)[3])MEM_malloc_arrayN(
mesh->totvert, sizeof(float[3]), __func__);
}
BLI_assert(MEM_allocN_len(mesh->runtime.vert_normals) >= sizeof(float[3]) * mesh->totvert);
BLI_assert(MEM_allocN_len(mesh->runtime->vert_normals) >= sizeof(float[3]) * mesh->totvert);
return mesh->runtime.vert_normals;
return mesh->runtime->vert_normals;
}
float (*BKE_mesh_poly_normals_for_write(Mesh *mesh))[3]
{
if (mesh->runtime.poly_normals == nullptr) {
mesh->runtime.poly_normals = (float(*)[3])MEM_malloc_arrayN(
if (mesh->runtime->poly_normals == nullptr) {
mesh->runtime->poly_normals = (float(*)[3])MEM_malloc_arrayN(
mesh->totpoly, sizeof(float[3]), __func__);
}
BLI_assert(MEM_allocN_len(mesh->runtime.poly_normals) >= sizeof(float[3]) * mesh->totpoly);
BLI_assert(MEM_allocN_len(mesh->runtime->poly_normals) >= sizeof(float[3]) * mesh->totpoly);
return mesh->runtime.poly_normals;
return mesh->runtime->poly_normals;
}
void BKE_mesh_vertex_normals_clear_dirty(Mesh *mesh)
{
mesh->runtime.vert_normals_dirty = false;
mesh->runtime->vert_normals_dirty = false;
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
}
void BKE_mesh_poly_normals_clear_dirty(Mesh *mesh)
{
mesh->runtime.poly_normals_dirty = false;
mesh->runtime->poly_normals_dirty = false;
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
}
bool BKE_mesh_vertex_normals_are_dirty(const Mesh *mesh)
{
return mesh->runtime.vert_normals_dirty;
return mesh->runtime->vert_normals_dirty;
}
bool BKE_mesh_poly_normals_are_dirty(const Mesh *mesh)
{
return mesh->runtime.poly_normals_dirty;
return mesh->runtime->poly_normals_dirty;
}
void BKE_mesh_clear_derived_normals(Mesh *mesh)
{
MEM_SAFE_FREE(mesh->runtime.vert_normals);
MEM_SAFE_FREE(mesh->runtime.poly_normals);
MEM_SAFE_FREE(mesh->runtime->vert_normals);
MEM_SAFE_FREE(mesh->runtime->poly_normals);
mesh->runtime.vert_normals_dirty = true;
mesh->runtime.poly_normals_dirty = true;
mesh->runtime->vert_normals_dirty = true;
mesh->runtime->poly_normals_dirty = true;
}
void BKE_mesh_assert_normals_dirty_or_calculated(const Mesh *mesh)
{
if (!mesh->runtime.vert_normals_dirty) {
BLI_assert(mesh->runtime.vert_normals || mesh->totvert == 0);
if (!mesh->runtime->vert_normals_dirty) {
BLI_assert(mesh->runtime->vert_normals || mesh->totvert == 0);
}
if (!mesh->runtime.poly_normals_dirty) {
BLI_assert(mesh->runtime.poly_normals || mesh->totpoly == 0);
if (!mesh->runtime->poly_normals_dirty) {
BLI_assert(mesh->runtime->poly_normals || mesh->totpoly == 0);
}
}
@ -348,20 +348,20 @@ void BKE_mesh_calc_normals_poly_and_vertex(const MVert *mvert,
const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
{
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
BLI_assert(mesh->runtime.vert_normals != nullptr || mesh->totvert == 0);
return mesh->runtime.vert_normals;
BLI_assert(mesh->runtime->vert_normals != nullptr || mesh->totvert == 0);
return mesh->runtime->vert_normals;
}
if (mesh->totvert == 0) {
return nullptr;
}
ThreadMutex *normals_mutex = (ThreadMutex *)mesh->runtime.normals_mutex;
ThreadMutex *normals_mutex = (ThreadMutex *)mesh->runtime->normals_mutex;
BLI_mutex_lock(normals_mutex);
if (!BKE_mesh_vertex_normals_are_dirty(mesh)) {
BLI_assert(mesh->runtime.vert_normals != nullptr);
BLI_assert(mesh->runtime->vert_normals != nullptr);
BLI_mutex_unlock(normals_mutex);
return mesh->runtime.vert_normals;
return mesh->runtime->vert_normals;
}
float(*vert_normals)[3];
@ -397,20 +397,20 @@ const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
{
if (!BKE_mesh_poly_normals_are_dirty(mesh)) {
BLI_assert(mesh->runtime.poly_normals != nullptr || mesh->totpoly == 0);
return mesh->runtime.poly_normals;
BLI_assert(mesh->runtime->poly_normals != nullptr || mesh->totpoly == 0);
return mesh->runtime->poly_normals;
}
if (mesh->totpoly == 0) {
return nullptr;
}
ThreadMutex *normals_mutex = (ThreadMutex *)mesh->runtime.normals_mutex;
ThreadMutex *normals_mutex = (ThreadMutex *)mesh->runtime->normals_mutex;
BLI_mutex_lock(normals_mutex);
if (!BKE_mesh_poly_normals_are_dirty(mesh)) {
BLI_assert(mesh->runtime.poly_normals != nullptr);
BLI_assert(mesh->runtime->poly_normals != nullptr);
BLI_mutex_unlock(normals_mutex);
return mesh->runtime.poly_normals;
return mesh->runtime->poly_normals;
}
float(*poly_normals)[3];
@ -441,7 +441,7 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
{
switch ((eMeshWrapperType)mesh->runtime.wrapper_type) {
switch (mesh->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_SUBD:
case ME_WRAPPER_TYPE_MDATA:
BKE_mesh_vertex_normals_ensure(mesh);
@ -449,7 +449,7 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
break;
case ME_WRAPPER_TYPE_BMESH: {
struct BMEditMesh *em = mesh->edit_mesh;
EditMeshData *emd = mesh->runtime.edit_data;
EditMeshData *emd = mesh->runtime->edit_data;
if (emd->vertexCos) {
BKE_editmesh_cache_ensure_vert_normals(em, emd);
BKE_editmesh_cache_ensure_poly_normals(em, emd);

View File

@ -1529,7 +1529,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
BLI_bitmap *looptri_active;
looptri_src = BKE_mesh_runtime_looptri_ensure(me_src);
num_looptri_src = me_src->runtime.looptris.len;
num_looptri_src = BKE_mesh_runtime_looptri_len(me_src);
looptri_active = BLI_BITMAP_NEW((size_t)num_looptri_src, __func__);
for (tindex = 0; tindex < num_trees; tindex++) {

View File

@ -17,6 +17,7 @@
#include "BLI_task.hh"
#include "BKE_bvhutils.h"
#include "BKE_editmesh_cache.h"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
@ -30,81 +31,50 @@ using blender::Span;
/** \name Mesh Runtime Struct Utils
* \{ */
/**
* \brief Initialize the runtime mutexes of the given mesh.
*
* Any existing mutexes will be overridden.
*/
static void mesh_runtime_init_mutexes(Mesh *mesh)
{
mesh->runtime.eval_mutex = MEM_new<ThreadMutex>("mesh runtime eval_mutex");
BLI_mutex_init(static_cast<ThreadMutex *>(mesh->runtime.eval_mutex));
mesh->runtime.normals_mutex = MEM_new<ThreadMutex>("mesh runtime normals_mutex");
BLI_mutex_init(static_cast<ThreadMutex *>(mesh->runtime.normals_mutex));
mesh->runtime.render_mutex = MEM_new<ThreadMutex>("mesh runtime render_mutex");
BLI_mutex_init(static_cast<ThreadMutex *>(mesh->runtime.render_mutex));
}
/**
* \brief free the mutexes of the given mesh runtime.
*/
static void mesh_runtime_free_mutexes(Mesh *mesh)
{
if (mesh->runtime.eval_mutex != nullptr) {
BLI_mutex_end(static_cast<ThreadMutex *>(mesh->runtime.eval_mutex));
MEM_freeN(mesh->runtime.eval_mutex);
mesh->runtime.eval_mutex = nullptr;
}
if (mesh->runtime.normals_mutex != nullptr) {
BLI_mutex_end(static_cast<ThreadMutex *>(mesh->runtime.normals_mutex));
MEM_freeN(mesh->runtime.normals_mutex);
mesh->runtime.normals_mutex = nullptr;
}
if (mesh->runtime.render_mutex != nullptr) {
BLI_mutex_end(static_cast<ThreadMutex *>(mesh->runtime.render_mutex));
MEM_freeN(mesh->runtime.render_mutex);
mesh->runtime.render_mutex = nullptr;
}
}
void BKE_mesh_runtime_init_data(Mesh *mesh)
{
mesh_runtime_init_mutexes(mesh);
}
void BKE_mesh_runtime_free_data(Mesh *mesh)
{
BKE_mesh_runtime_clear_cache(mesh);
mesh_runtime_free_mutexes(mesh);
}
void BKE_mesh_runtime_reset_on_copy(Mesh *mesh, const int /*flag*/)
namespace blender::bke {
MeshRuntime::MeshRuntime()
{
Mesh_Runtime *runtime = &mesh->runtime;
runtime->mesh_eval = nullptr;
runtime->edit_data = nullptr;
runtime->batch_cache = nullptr;
runtime->subdiv_ccg = nullptr;
runtime->looptris = blender::dna::shallow_zero_initialize();
runtime->bvh_cache = nullptr;
runtime->shrinkwrap_data = nullptr;
runtime->subsurf_face_dot_tags = nullptr;
runtime->vert_normals_dirty = true;
runtime->poly_normals_dirty = true;
runtime->vert_normals = nullptr;
runtime->poly_normals = nullptr;
mesh_runtime_init_mutexes(mesh);
this->eval_mutex = MEM_new<ThreadMutex>("mesh runtime eval_mutex");
BLI_mutex_init(static_cast<ThreadMutex *>(this->eval_mutex));
this->normals_mutex = MEM_new<ThreadMutex>("mesh runtime normals_mutex");
BLI_mutex_init(static_cast<ThreadMutex *>(this->normals_mutex));
this->render_mutex = MEM_new<ThreadMutex>("mesh runtime render_mutex");
BLI_mutex_init(static_cast<ThreadMutex *>(this->render_mutex));
}
MeshRuntime::~MeshRuntime()
{
if (this->eval_mutex != nullptr) {
BLI_mutex_end(static_cast<ThreadMutex *>(this->eval_mutex));
MEM_freeN(this->eval_mutex);
this->eval_mutex = nullptr;
}
if (this->normals_mutex != nullptr) {
BLI_mutex_end(static_cast<ThreadMutex *>(this->normals_mutex));
MEM_freeN(this->normals_mutex);
this->normals_mutex = nullptr;
}
if (this->render_mutex != nullptr) {
BLI_mutex_end(static_cast<ThreadMutex *>(this->render_mutex));
MEM_freeN(this->render_mutex);
this->render_mutex = nullptr;
}
}
} // namespace blender::bke
void BKE_mesh_runtime_clear_cache(Mesh *mesh)
{
if (mesh->runtime.mesh_eval != nullptr) {
mesh->runtime.mesh_eval->edit_mesh = nullptr;
BKE_id_free(nullptr, mesh->runtime.mesh_eval);
mesh->runtime.mesh_eval = nullptr;
if (mesh->runtime->mesh_eval != nullptr) {
mesh->runtime->mesh_eval->edit_mesh = nullptr;
BKE_id_free(nullptr, mesh->runtime->mesh_eval);
mesh->runtime->mesh_eval = nullptr;
}
BKE_mesh_runtime_clear_geometry(mesh);
BKE_mesh_batch_cache_free(mesh);
@ -131,32 +101,32 @@ static void mesh_ensure_looptri_data(Mesh *mesh)
const uint totpoly = mesh->totpoly;
const int looptris_len = poly_to_tri_count(totpoly, mesh->totloop);
BLI_assert(mesh->runtime.looptris.array_wip == nullptr);
BLI_assert(mesh->runtime->looptris.array_wip == nullptr);
SWAP(MLoopTri *, mesh->runtime.looptris.array, mesh->runtime.looptris.array_wip);
SWAP(MLoopTri *, mesh->runtime->looptris.array, mesh->runtime->looptris.array_wip);
if ((looptris_len > mesh->runtime.looptris.len_alloc) ||
(looptris_len < mesh->runtime.looptris.len_alloc * 2) || (totpoly == 0)) {
MEM_SAFE_FREE(mesh->runtime.looptris.array_wip);
mesh->runtime.looptris.len_alloc = 0;
mesh->runtime.looptris.len = 0;
if ((looptris_len > mesh->runtime->looptris.len_alloc) ||
(looptris_len < mesh->runtime->looptris.len_alloc * 2) || (totpoly == 0)) {
MEM_SAFE_FREE(mesh->runtime->looptris.array_wip);
mesh->runtime->looptris.len_alloc = 0;
mesh->runtime->looptris.len = 0;
}
if (totpoly) {
if (mesh->runtime.looptris.array_wip == nullptr) {
mesh->runtime.looptris.array_wip = static_cast<MLoopTri *>(
MEM_malloc_arrayN(looptris_len, sizeof(*mesh->runtime.looptris.array_wip), __func__));
mesh->runtime.looptris.len_alloc = looptris_len;
if (mesh->runtime->looptris.array_wip == nullptr) {
mesh->runtime->looptris.array_wip = static_cast<MLoopTri *>(
MEM_malloc_arrayN(looptris_len, sizeof(*mesh->runtime->looptris.array_wip), __func__));
mesh->runtime->looptris.len_alloc = looptris_len;
}
mesh->runtime.looptris.len = looptris_len;
mesh->runtime->looptris.len = looptris_len;
}
}
void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
{
mesh_ensure_looptri_data(mesh);
BLI_assert(mesh->totpoly == 0 || mesh->runtime.looptris.array_wip != nullptr);
BLI_assert(mesh->totpoly == 0 || mesh->runtime->looptris.array_wip != nullptr);
const Span<MVert> verts = mesh->verts();
const Span<MPoly> polys = mesh->polys();
const Span<MLoop> loops = mesh->loops();
@ -167,7 +137,7 @@ void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
verts.data(),
mesh->totloop,
mesh->totpoly,
mesh->runtime.looptris.array_wip,
mesh->runtime->looptris.array_wip,
BKE_mesh_poly_normals_ensure(mesh));
}
else {
@ -176,39 +146,39 @@ void BKE_mesh_runtime_looptri_recalc(Mesh *mesh)
verts.data(),
mesh->totloop,
mesh->totpoly,
mesh->runtime.looptris.array_wip);
mesh->runtime->looptris.array_wip);
}
BLI_assert(mesh->runtime.looptris.array == nullptr);
atomic_cas_ptr((void **)&mesh->runtime.looptris.array,
mesh->runtime.looptris.array,
mesh->runtime.looptris.array_wip);
mesh->runtime.looptris.array_wip = nullptr;
BLI_assert(mesh->runtime->looptris.array == nullptr);
atomic_cas_ptr((void **)&mesh->runtime->looptris.array,
mesh->runtime->looptris.array,
mesh->runtime->looptris.array_wip);
mesh->runtime->looptris.array_wip = nullptr;
}
int BKE_mesh_runtime_looptri_len(const Mesh *mesh)
{
/* This is a ported copy of `dm_getNumLoopTri(dm)`. */
const int looptri_len = poly_to_tri_count(mesh->totpoly, mesh->totloop);
BLI_assert(ELEM(mesh->runtime.looptris.len, 0, looptri_len));
BLI_assert(ELEM(mesh->runtime->looptris.len, 0, looptri_len));
return looptri_len;
}
const MLoopTri *BKE_mesh_runtime_looptri_ensure(const Mesh *mesh)
{
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime->eval_mutex;
BLI_mutex_lock(mesh_eval_mutex);
MLoopTri *looptri = mesh->runtime.looptris.array;
MLoopTri *looptri = mesh->runtime->looptris.array;
if (looptri != nullptr) {
BLI_assert(BKE_mesh_runtime_looptri_len(mesh) == mesh->runtime.looptris.len);
BLI_assert(BKE_mesh_runtime_looptri_len(mesh) == mesh->runtime->looptris.len);
}
else {
/* Must isolate multithreaded tasks while holding a mutex lock. */
blender::threading::isolate_task(
[&]() { BKE_mesh_runtime_looptri_recalc(const_cast<Mesh *>(mesh)); });
looptri = mesh->runtime.looptris.array;
looptri = mesh->runtime->looptris.array;
}
BLI_mutex_unlock(mesh_eval_mutex);
@ -230,17 +200,17 @@ void BKE_mesh_runtime_verttri_from_looptri(MVertTri *r_verttri,
bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh)
{
if (mesh->runtime.edit_data != nullptr) {
if (mesh->runtime->edit_data != nullptr) {
return false;
}
mesh->runtime.edit_data = MEM_cnew<EditMeshData>(__func__);
mesh->runtime->edit_data = MEM_cnew<EditMeshData>(__func__);
return true;
}
bool BKE_mesh_runtime_reset_edit_data(Mesh *mesh)
{
EditMeshData *edit_data = mesh->runtime.edit_data;
EditMeshData *edit_data = mesh->runtime->edit_data;
if (edit_data == nullptr) {
return false;
}
@ -255,13 +225,13 @@ bool BKE_mesh_runtime_reset_edit_data(Mesh *mesh)
bool BKE_mesh_runtime_clear_edit_data(Mesh *mesh)
{
if (mesh->runtime.edit_data == nullptr) {
if (mesh->runtime->edit_data == nullptr) {
return false;
}
BKE_mesh_runtime_reset_edit_data(mesh);
MEM_freeN(mesh->runtime.edit_data);
mesh->runtime.edit_data = nullptr;
MEM_freeN(mesh->runtime->edit_data);
mesh->runtime->edit_data = nullptr;
return true;
}
@ -271,22 +241,22 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
BKE_mesh_tag_coords_changed(mesh);
/* TODO(sergey): Does this really belong here? */
if (mesh->runtime.subdiv_ccg != nullptr) {
BKE_subdiv_ccg_destroy(mesh->runtime.subdiv_ccg);
mesh->runtime.subdiv_ccg = nullptr;
if (mesh->runtime->subdiv_ccg != nullptr) {
BKE_subdiv_ccg_destroy(mesh->runtime->subdiv_ccg);
mesh->runtime->subdiv_ccg = nullptr;
}
BKE_shrinkwrap_discard_boundary_data(mesh);
MEM_SAFE_FREE(mesh->runtime.subsurf_face_dot_tags);
MEM_SAFE_FREE(mesh->runtime->subsurf_face_dot_tags);
}
void BKE_mesh_tag_coords_changed(Mesh *mesh)
{
BKE_mesh_normals_tag_dirty(mesh);
MEM_SAFE_FREE(mesh->runtime.looptris.array);
if (mesh->runtime.bvh_cache) {
bvhcache_free(mesh->runtime.bvh_cache);
mesh->runtime.bvh_cache = nullptr;
MEM_SAFE_FREE(mesh->runtime->looptris.array);
if (mesh->runtime->bvh_cache) {
bvhcache_free(mesh->runtime->bvh_cache);
mesh->runtime->bvh_cache = nullptr;
}
}
@ -305,6 +275,16 @@ void BKE_mesh_tag_coords_changed_uniformly(Mesh *mesh)
}
}
bool BKE_mesh_is_deformed_only(const Mesh *mesh)
{
return mesh->runtime->deformed_only;
}
eMeshWrapperType BKE_mesh_wrapper_type(const struct Mesh *mesh)
{
return mesh->runtime->wrapper_type;
}
/** \} */
/* -------------------------------------------------------------------- */
@ -317,13 +297,13 @@ void (*BKE_mesh_batch_cache_free_cb)(Mesh *me) = nullptr;
void BKE_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
{
if (me->runtime.batch_cache) {
if (me->runtime->batch_cache) {
BKE_mesh_batch_cache_dirty_tag_cb(me, mode);
}
}
void BKE_mesh_batch_cache_free(Mesh *me)
{
if (me->runtime.batch_cache) {
if (me->runtime->batch_cache) {
BKE_mesh_batch_cache_free_cb(me);
}
}

View File

@ -570,8 +570,6 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
const char (*tangent_names)[MAX_NAME],
int tangent_names_len)
{
BKE_mesh_runtime_looptri_ensure(me_eval);
/* TODO(@campbellbarton): store in Mesh.runtime to avoid recalculation. */
short tangent_mask = 0;
BKE_mesh_calc_loop_tangent_ex(
@ -579,8 +577,8 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
BKE_mesh_polys(me_eval),
uint(me_eval->totpoly),
BKE_mesh_loops(me_eval),
me_eval->runtime.looptris.array,
uint(me_eval->runtime.looptris.len),
BKE_mesh_runtime_looptri_ensure(me_eval),
uint(BKE_mesh_runtime_looptri_len(me_eval)),
&me_eval->ldata,
calc_active_tangent,
tangent_names,

View File

@ -57,13 +57,13 @@ Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
BKE_mesh_copy_parameters_for_eval(me, me_settings);
BKE_mesh_runtime_ensure_edit_data(me);
me->runtime.wrapper_type = ME_WRAPPER_TYPE_BMESH;
me->runtime->wrapper_type = ME_WRAPPER_TYPE_BMESH;
if (cd_mask_extra) {
me->runtime.cd_mask_extra = *cd_mask_extra;
me->runtime->cd_mask_extra = *cd_mask_extra;
}
/* Use edit-mesh directly where possible. */
me->runtime.is_original_bmesh = true;
me->runtime->is_original_bmesh = true;
me->edit_mesh = static_cast<BMEditMesh *>(MEM_dupallocN(em));
me->edit_mesh->is_shallow_copy = true;
@ -81,7 +81,7 @@ Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em,
me->totloop = 0;
#endif
EditMeshData *edit_data = me->runtime.edit_data;
EditMeshData *edit_data = me->runtime->edit_data;
edit_data->vertexCos = vert_coords;
return me;
}
@ -95,17 +95,17 @@ Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em,
void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
{
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)me->runtime.eval_mutex;
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)me->runtime->eval_mutex;
BLI_mutex_lock(mesh_eval_mutex);
if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
if (me->runtime->wrapper_type == ME_WRAPPER_TYPE_MDATA) {
BLI_mutex_unlock(mesh_eval_mutex);
return;
}
/* Must isolate multithreaded tasks while holding a mutex lock. */
blender::threading::isolate_task([&]() {
switch (static_cast<eMeshWrapperType>(me->runtime.wrapper_type)) {
switch (static_cast<eMeshWrapperType>(me->runtime->wrapper_type)) {
case ME_WRAPPER_TYPE_MDATA:
case ME_WRAPPER_TYPE_SUBD: {
break; /* Quiet warning. */
@ -117,10 +117,10 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
me->totloop = 0;
BLI_assert(me->edit_mesh != nullptr);
BLI_assert(me->runtime.edit_data != nullptr);
BLI_assert(me->runtime->edit_data != nullptr);
BMEditMesh *em = me->edit_mesh;
BM_mesh_bm_to_me_for_eval(em->bm, me, &me->runtime.cd_mask_extra);
BM_mesh_bm_to_me_for_eval(em->bm, me, &me->runtime->cd_mask_extra);
/* Adding original index layers assumes that all BMesh mesh wrappers are created from
* original edit mode meshes (the only case where adding original indices makes sense).
@ -132,22 +132,22 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
* harmful. */
BKE_mesh_ensure_default_orig_index_customdata_no_check(me);
EditMeshData *edit_data = me->runtime.edit_data;
EditMeshData *edit_data = me->runtime->edit_data;
if (edit_data->vertexCos) {
BKE_mesh_vert_coords_apply(me, edit_data->vertexCos);
me->runtime.is_original_bmesh = false;
me->runtime->is_original_bmesh = false;
}
break;
}
}
if (me->runtime.wrapper_type_finalize) {
BKE_mesh_wrapper_deferred_finalize_mdata(me, &me->runtime.cd_mask_extra);
if (me->runtime->wrapper_type_finalize) {
BKE_mesh_wrapper_deferred_finalize_mdata(me, &me->runtime->cd_mask_extra);
}
/* Keep type assignment last, so that read-only access only uses the mdata code paths after all
* the underlying data has been initialized. */
me->runtime.wrapper_type = ME_WRAPPER_TYPE_MDATA;
me->runtime->wrapper_type = ME_WRAPPER_TYPE_MDATA;
});
BLI_mutex_unlock(mesh_eval_mutex);
@ -155,9 +155,9 @@ void BKE_mesh_wrapper_ensure_mdata(Mesh *me)
bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3])
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
return BKE_editmesh_cache_calc_minmax(me->edit_mesh, me->runtime.edit_data, min, max);
return BKE_editmesh_cache_calc_minmax(me->edit_mesh, me->runtime->edit_data, min, max);
case ME_WRAPPER_TYPE_MDATA:
case ME_WRAPPER_TYPE_SUBD:
return BKE_mesh_minmax(me, min, max);
@ -174,11 +174,11 @@ void BKE_mesh_wrapper_vert_coords_copy(const Mesh *me,
float (*vert_coords)[3],
int vert_coords_len)
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH: {
BMesh *bm = me->edit_mesh->bm;
BLI_assert(vert_coords_len <= bm->totvert);
EditMeshData *edit_data = me->runtime.edit_data;
EditMeshData *edit_data = me->runtime->edit_data;
if (edit_data->vertexCos != nullptr) {
for (int i = 0; i < vert_coords_len; i++) {
copy_v3_v3(vert_coords[i], edit_data->vertexCos[i]);
@ -212,11 +212,11 @@ void BKE_mesh_wrapper_vert_coords_copy_with_mat4(const Mesh *me,
int vert_coords_len,
const float mat[4][4])
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH: {
BMesh *bm = me->edit_mesh->bm;
BLI_assert(vert_coords_len == bm->totvert);
EditMeshData *edit_data = me->runtime.edit_data;
EditMeshData *edit_data = me->runtime->edit_data;
if (edit_data->vertexCos != nullptr) {
for (int i = 0; i < vert_coords_len; i++) {
mul_v3_m4v3(vert_coords[i], mat, edit_data->vertexCos[i]);
@ -253,7 +253,7 @@ void BKE_mesh_wrapper_vert_coords_copy_with_mat4(const Mesh *me,
int BKE_mesh_wrapper_vert_len(const Mesh *me)
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
return me->edit_mesh->bm->totvert;
case ME_WRAPPER_TYPE_MDATA:
@ -266,7 +266,7 @@ int BKE_mesh_wrapper_vert_len(const Mesh *me)
int BKE_mesh_wrapper_edge_len(const Mesh *me)
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
return me->edit_mesh->bm->totedge;
case ME_WRAPPER_TYPE_MDATA:
@ -279,7 +279,7 @@ int BKE_mesh_wrapper_edge_len(const Mesh *me)
int BKE_mesh_wrapper_loop_len(const Mesh *me)
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
return me->edit_mesh->bm->totloop;
case ME_WRAPPER_TYPE_MDATA:
@ -292,7 +292,7 @@ int BKE_mesh_wrapper_loop_len(const Mesh *me)
int BKE_mesh_wrapper_poly_len(const Mesh *me)
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH:
return me->edit_mesh->bm->totface;
case ME_WRAPPER_TYPE_MDATA:
@ -311,7 +311,7 @@ int BKE_mesh_wrapper_poly_len(const Mesh *me)
static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me)
{
SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)me->runtime.subsurf_runtime_data;
SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)me->runtime->subsurf_runtime_data;
if (runtime_data == nullptr || runtime_data->settings.level == 0) {
return me;
}
@ -359,24 +359,24 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me)
}
if (subdiv_mesh != me) {
if (me->runtime.mesh_eval != nullptr) {
BKE_id_free(nullptr, me->runtime.mesh_eval);
if (me->runtime->mesh_eval != nullptr) {
BKE_id_free(nullptr, me->runtime->mesh_eval);
}
me->runtime.mesh_eval = subdiv_mesh;
me->runtime.wrapper_type = ME_WRAPPER_TYPE_SUBD;
me->runtime->mesh_eval = subdiv_mesh;
me->runtime->wrapper_type = ME_WRAPPER_TYPE_SUBD;
}
return me->runtime.mesh_eval;
return me->runtime->mesh_eval;
}
Mesh *BKE_mesh_wrapper_ensure_subdivision(Mesh *me)
{
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)me->runtime.eval_mutex;
ThreadMutex *mesh_eval_mutex = (ThreadMutex *)me->runtime->eval_mutex;
BLI_mutex_lock(mesh_eval_mutex);
if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_SUBD) {
if (me->runtime->wrapper_type == ME_WRAPPER_TYPE_SUBD) {
BLI_mutex_unlock(mesh_eval_mutex);
return me->runtime.mesh_eval;
return me->runtime->mesh_eval;
}
Mesh *result;

View File

@ -963,9 +963,9 @@ void BKE_modifier_path_init(char *path, int path_maxlen, const char *name)
*/
static void modwrap_dependsOnNormals(Mesh *me)
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH: {
EditMeshData *edit_data = me->runtime.edit_data;
EditMeshData *edit_data = me->runtime->edit_data;
if (edit_data->vertexCos) {
/* Note that 'ensure' is acceptable here since these values aren't modified in-place.
* If that changes we'll need to recalculate. */
@ -993,7 +993,7 @@ struct Mesh *BKE_modifier_modify_mesh(ModifierData *md,
{
const ModifierTypeInfo *mti = BKE_modifier_get_info(ModifierType(md->type));
if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
if (me->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
if ((mti->flags & eModifierTypeFlag_AcceptsBMesh) == 0) {
BKE_mesh_wrapper_ensure_mdata(me);
}

View File

@ -397,7 +397,7 @@ void multires_mark_as_modified(Depsgraph *depsgraph, Object *object, MultiresMod
* In a longer term maybe special dependency graph tag can help sanitizing this a bit. */
Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
Mesh *mesh = static_cast<Mesh *>(object_eval->data);
SubdivCCG *subdiv_ccg = mesh->runtime.subdiv_ccg;
SubdivCCG *subdiv_ccg = mesh->runtime->subdiv_ccg;
if (subdiv_ccg == nullptr) {
return;
}

View File

@ -1691,7 +1691,7 @@ static void object_update_from_subsurf_ccg(Object *object)
if (mesh_eval == nullptr) {
return;
}
SubdivCCG *subdiv_ccg = mesh_eval->runtime.subdiv_ccg;
SubdivCCG *subdiv_ccg = mesh_eval->runtime->subdiv_ccg;
if (subdiv_ccg == nullptr) {
return;
}
@ -1699,7 +1699,7 @@ static void object_update_from_subsurf_ccg(Object *object)
if (!subdiv_ccg->dirty.coords && !subdiv_ccg->dirty.hidden) {
return;
}
const int tot_level = mesh_eval->runtime.subdiv_ccg_tot_level;
const int tot_level = mesh_eval->runtime->subdiv_ccg_tot_level;
Object *object_orig = DEG_get_original_object(object);
Mesh *mesh_orig = (Mesh *)object_orig->data;
multiresModifier_reshapeFromCCG(tot_level, mesh_orig, subdiv_ccg);
@ -3218,7 +3218,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
int count = 0;
int numVerts = me_eval->totvert;
if (em && me_eval->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
if (em && me_eval->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
numVerts = em->bm->totvert;
if (em->bm->elem_table_dirty & BM_VERT) {
#ifdef VPARENT_THREADING_HACK
@ -3233,8 +3233,8 @@ static void give_parvert(Object *par, int nr, float vec[3])
#endif
}
if (nr < numVerts) {
if (me_eval && me_eval->runtime.edit_data && me_eval->runtime.edit_data->vertexCos) {
add_v3_v3(vec, me_eval->runtime.edit_data->vertexCos[nr]);
if (me_eval && me_eval->runtime->edit_data && me_eval->runtime->edit_data->vertexCos) {
add_v3_v3(vec, me_eval->runtime->edit_data->vertexCos[nr]);
}
else {
const BMVert *v = BM_vert_at_index(em->bm, nr);

View File

@ -423,8 +423,8 @@ static const Mesh *mesh_data_from_duplicator_object(Object *ob,
/* Note that this will only show deformation if #eModifierMode_OnCage is enabled.
* We could change this but it matches 2.7x behavior. */
me_eval = BKE_object_get_editmesh_eval_cage(ob);
if ((me_eval == nullptr) || (me_eval->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
EditMeshData *emd = me_eval ? me_eval->runtime.edit_data : nullptr;
if ((me_eval == nullptr) || (me_eval->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
EditMeshData *emd = me_eval ? me_eval->runtime->edit_data : nullptr;
/* Only assign edit-mesh in the case we can't use `me_eval`. */
*r_em = em;

View File

@ -373,7 +373,7 @@ void BKE_object_select_update(Depsgraph *depsgraph, Object *object)
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
if (object->type == OB_MESH && !object->runtime.is_data_eval_owned) {
Mesh *mesh_input = (Mesh *)object->runtime.data_orig;
Mesh_Runtime *mesh_runtime = &mesh_input->runtime;
blender::bke::MeshRuntime *mesh_runtime = mesh_input->runtime;
BLI_mutex_lock(static_cast<ThreadMutex *>(mesh_runtime->eval_mutex));
BKE_object_data_select_update(depsgraph, static_cast<ID *>(object->data));
BLI_mutex_unlock(static_cast<ThreadMutex *>(mesh_runtime->eval_mutex));

View File

@ -1743,7 +1743,7 @@ static void sculpt_update_object(
ss->hide_poly = (bool *)CustomData_get_layer_named(&me->pdata, CD_PROP_BOOL, ".hide_poly");
ss->subdiv_ccg = me_eval->runtime.subdiv_ccg;
ss->subdiv_ccg = me_eval->runtime->subdiv_ccg;
PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
BLI_assert(pbvh == ss->pbvh);
@ -2258,7 +2258,7 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) {
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Mesh *mesh_eval = static_cast<Mesh *>(object_eval->data);
SubdivCCG *subdiv_ccg = mesh_eval->runtime.subdiv_ccg;
SubdivCCG *subdiv_ccg = mesh_eval->runtime->subdiv_ccg;
if (subdiv_ccg != nullptr) {
BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg);
}
@ -2277,8 +2277,8 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
else {
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Mesh *mesh_eval = static_cast<Mesh *>(object_eval->data);
if (mesh_eval->runtime.subdiv_ccg != nullptr) {
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime.subdiv_ccg, respect_hide);
if (mesh_eval->runtime->subdiv_ccg != nullptr) {
pbvh = build_pbvh_from_ccg(ob, mesh_eval->runtime->subdiv_ccg, respect_hide);
}
else if (ob->type == OB_MESH) {
Mesh *me_eval_deform = object_eval->runtime.mesh_deform_eval;

View File

@ -60,6 +60,7 @@
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_mesh_legacy_convert.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@ -1933,7 +1934,7 @@ int psys_particle_dm_face_lookup(Mesh *mesh_final,
index_mf_to_mpoly_deformed = CustomData_get_layer(&mesh_original->fdata, CD_ORIGINDEX);
}
else {
BLI_assert(mesh_final->runtime.deformed_only);
BLI_assert(BKE_mesh_is_deformed_only(mesh_final));
index_mf_to_mpoly_deformed = index_mf_to_mpoly;
}
BLI_assert(index_mf_to_mpoly_deformed);
@ -2023,7 +2024,7 @@ static int psys_map_index_on_dm(Mesh *mesh,
return 0;
}
if (mesh->runtime.deformed_only || index_dmcache == DMCACHE_ISCHILD) {
if (BKE_mesh_is_deformed_only(mesh) || index_dmcache == DMCACHE_ISCHILD) {
/* for meshes that are either only deformed or for child particles, the
* index and fw do not require any mapping, so we can directly use it */
if (from == PART_FROM_VERT) {

View File

@ -29,6 +29,7 @@
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_legacy_convert.h"
#include "BKE_mesh_runtime.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@ -899,7 +900,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
return 0;
}
if (!final_mesh->runtime.deformed_only &&
if (!BKE_mesh_is_deformed_only(final_mesh) &&
!CustomData_get_layer(&final_mesh->fdata, CD_ORIGINDEX)) {
printf(
"Can't create particles with the current modifier stack, disable destructive modifiers\n");

View File

@ -48,6 +48,7 @@
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_mesh_legacy_convert.h"
#include "BKE_mesh_runtime.h"
#include "BKE_particle.h"
#include "BKE_bvhutils.h"
@ -319,7 +320,7 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, Partic
PARTICLE_P;
/* CACHE LOCATIONS */
if (!mesh_final->runtime.deformed_only) {
if (!BKE_mesh_is_deformed_only(mesh_final)) {
/* Will use later to speed up subsurf/evaluated mesh. */
LinkNode *node, *nodedmelem, **nodearray;
int totdmelem, totelem, i;

View File

@ -404,7 +404,7 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
const MVert *mvert = BKE_mesh_verts(mesh);
totvert = mesh->totvert;
looptri = BKE_mesh_runtime_looptri_ensure(mesh);
tottri = mesh->runtime.looptris.len;
tottri = BKE_mesh_runtime_looptri_len(mesh);
const MLoop *mloop = BKE_mesh_loops(mesh);
/* sanity checking - potential case when no data will be present */
@ -679,7 +679,7 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
const MVert *mvert = BKE_mesh_verts(mesh);
totvert = mesh->totvert;
lt = BKE_mesh_runtime_looptri_ensure(mesh);
tottri = mesh->runtime.looptris.len;
tottri = BKE_mesh_runtime_looptri_len(mesh);
const MLoop *mloop = BKE_mesh_loops(mesh);
if (totvert > 0 && tottri > 0) {
@ -753,7 +753,7 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3])
const MVert *mvert = BKE_mesh_verts(mesh);
totvert = mesh->totvert;
looptri = BKE_mesh_runtime_looptri_ensure(mesh);
tottri = mesh->runtime.looptris.len;
tottri = BKE_mesh_runtime_looptri_len(mesh);
const MLoop *mloop = BKE_mesh_loops(mesh);
if (totvert > 0 && tottri > 0) {

View File

@ -140,7 +140,7 @@ bool BKE_shrinkwrap_init_tree(
}
if (shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
data->boundary = mesh->runtime.shrinkwrap_data;
data->boundary = mesh->runtime->shrinkwrap_data;
}
return true;
@ -153,7 +153,7 @@ void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *data)
void BKE_shrinkwrap_discard_boundary_data(Mesh *mesh)
{
ShrinkwrapBoundaryData *data = mesh->runtime.shrinkwrap_data;
ShrinkwrapBoundaryData *data = mesh->runtime->shrinkwrap_data;
if (data != nullptr) {
MEM_freeN((void *)data->edge_is_boundary);
@ -164,7 +164,7 @@ void BKE_shrinkwrap_discard_boundary_data(Mesh *mesh)
MEM_freeN(data);
}
mesh->runtime.shrinkwrap_data = nullptr;
mesh->runtime->shrinkwrap_data = nullptr;
}
/* Accumulate edge for average boundary edge direction. */
@ -327,7 +327,7 @@ void BKE_shrinkwrap_compute_boundary_data(Mesh *mesh)
{
BKE_shrinkwrap_discard_boundary_data(mesh);
mesh->runtime.shrinkwrap_data = shrinkwrap_build_boundary_data(mesh);
mesh->runtime->shrinkwrap_data = shrinkwrap_build_boundary_data(mesh);
}
/**

View File

@ -615,7 +615,7 @@ Mesh *BKE_subdiv_to_ccg_mesh(Subdiv *subdiv,
return nullptr;
}
Mesh *result = BKE_mesh_new_nomain_from_template(coarse_mesh, 0, 0, 0, 0, 0);
result->runtime.subdiv_ccg = subdiv_ccg;
result->runtime->subdiv_ccg = subdiv_ccg;
return result;
}

View File

@ -528,9 +528,9 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_loops, num_polygons, mask);
subdiv_mesh_ctx_cache_custom_data_layers(subdiv_context);
subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices);
MEM_SAFE_FREE(subdiv_context->subdiv_mesh->runtime.subsurf_face_dot_tags);
subdiv_context->subdiv_mesh->runtime.subsurf_face_dot_tags = BLI_BITMAP_NEW(num_vertices,
__func__);
MEM_SAFE_FREE(subdiv_context->subdiv_mesh->runtime->subsurf_face_dot_tags);
subdiv_context->subdiv_mesh->runtime->subsurf_face_dot_tags = BLI_BITMAP_NEW(num_vertices,
__func__);
return true;
}
@ -595,7 +595,7 @@ static void evaluate_vertex_and_apply_displacement_copy(const SubdivMeshContext
/* Evaluate undeformed texture coordinate. */
subdiv_vertex_orco_evaluate(ctx, ptex_face_index, u, v, subdiv_vertex_index);
/* Remove face-dot flag. This can happen if there is more than one subsurf modifier. */
BLI_BITMAP_DISABLE(ctx->subdiv_mesh->runtime.subsurf_face_dot_tags, subdiv_vertex_index);
BLI_BITMAP_DISABLE(ctx->subdiv_mesh->runtime->subsurf_face_dot_tags, subdiv_vertex_index);
}
static void evaluate_vertex_and_apply_displacement_interpolate(
@ -753,7 +753,7 @@ static void subdiv_mesh_tag_center_vertex(const MPoly *coarse_poly,
Mesh *subdiv_mesh)
{
if (subdiv_mesh_is_center_vertex(coarse_poly, u, v)) {
BLI_BITMAP_ENABLE(subdiv_mesh->runtime.subsurf_face_dot_tags, subdiv_vertex_index);
BLI_BITMAP_ENABLE(subdiv_mesh->runtime->subsurf_face_dot_tags, subdiv_vertex_index);
}
}

View File

@ -11,6 +11,7 @@
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_subdiv.h"
@ -143,7 +144,7 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene,
bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh)
{
SubsurfRuntimeData *runtime_data = mesh->runtime.subsurf_runtime_data;
SubsurfRuntimeData *runtime_data = mesh->runtime->subsurf_runtime_data;
return runtime_data && runtime_data->has_gpu_subdiv;
}

View File

@ -1238,7 +1238,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *
* different than the BMesh's. */
BKE_mesh_clear_derived_normals(me);
me->runtime.deformed_only = true;
me->runtime->deformed_only = true;
bke::MutableAttributeAccessor mesh_attributes = me->attributes_for_write();

View File

@ -14,6 +14,7 @@
#include "BLI_alloca.h"
#include "BKE_editmesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@ -231,7 +232,7 @@ static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd,
static const CustomData *workbench_mesh_get_loop_custom_data(const Mesh *mesh)
{
if (mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
if (BKE_mesh_wrapper_type(mesh) == ME_WRAPPER_TYPE_BMESH) {
BLI_assert(mesh->edit_mesh != NULL);
BLI_assert(mesh->edit_mesh->bm != NULL);
return &mesh->edit_mesh->bm->ldata;
@ -241,7 +242,7 @@ static const CustomData *workbench_mesh_get_loop_custom_data(const Mesh *mesh)
static const CustomData *workbench_mesh_get_vert_custom_data(const Mesh *mesh)
{
if (mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
if (BKE_mesh_wrapper_type(mesh) == ME_WRAPPER_TYPE_BMESH) {
BLI_assert(mesh->edit_mesh != NULL);
BLI_assert(mesh->edit_mesh->bm != NULL);
return &mesh->edit_mesh->bm->vdata;

View File

@ -686,7 +686,7 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
MeshRenderData *mr = mesh_render_data_create(
object, me, is_editmode, is_paint_mode, is_mode_active, obmat, do_final, do_uvedit, ts);
mr->use_hide = use_hide;
mr->use_subsurf_fdots = mr->me && mr->me->runtime.subsurf_face_dot_tags != nullptr;
mr->use_subsurf_fdots = mr->me && mr->me->runtime->subsurf_face_dot_tags != nullptr;
mr->use_final_mesh = do_final;
#ifdef DEBUG_TIME

View File

@ -463,7 +463,7 @@ MeshRenderData *mesh_render_data_create(Object *object,
mr->bm = me->edit_mesh->bm;
mr->edit_bmesh = me->edit_mesh;
mr->me = (do_final) ? editmesh_eval_final : editmesh_eval_cage;
mr->edit_data = is_mode_active ? mr->me->runtime.edit_data : nullptr;
mr->edit_data = is_mode_active ? mr->me->runtime->edit_data : nullptr;
if (mr->edit_data) {
EditMeshData *emd = mr->edit_data;
@ -499,8 +499,8 @@ MeshRenderData *mesh_render_data_create(Object *object,
/* Use bmesh directly when the object is in edit mode unchanged by any modifiers.
* For non-final UVs, always use original bmesh since the UV editor does not support
* using the cage mesh with deformed coordinates. */
if ((is_mode_active && mr->me->runtime.is_original_bmesh &&
mr->me->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) ||
if ((is_mode_active && mr->me->runtime->is_original_bmesh &&
mr->me->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) ||
(do_uvedit && !do_final)) {
mr->extract_type = MR_EXTRACT_BMESH;
}

View File

@ -554,7 +554,7 @@ BLI_INLINE void mesh_batch_cache_add_request(MeshBatchCache *cache, DRWBatchFlag
static bool mesh_batch_cache_valid(Object *object, Mesh *me)
{
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime.batch_cache);
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime->batch_cache);
if (cache == nullptr) {
return false;
@ -588,11 +588,11 @@ static bool mesh_batch_cache_valid(Object *object, Mesh *me)
static void mesh_batch_cache_init(Object *object, Mesh *me)
{
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime.batch_cache);
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime->batch_cache);
if (!cache) {
me->runtime.batch_cache = MEM_cnew<MeshBatchCache>(__func__);
cache = static_cast<MeshBatchCache *>(me->runtime.batch_cache);
me->runtime->batch_cache = MEM_cnew<MeshBatchCache>(__func__);
cache = static_cast<MeshBatchCache *>(me->runtime->batch_cache);
}
else {
memset(cache, 0, sizeof(*cache));
@ -634,7 +634,7 @@ void DRW_mesh_batch_cache_validate(Object *object, Mesh *me)
static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
{
return static_cast<MeshBatchCache *>(me->runtime.batch_cache);
return static_cast<MeshBatchCache *>(me->runtime->batch_cache);
}
static void mesh_batch_cache_check_vertex_group(MeshBatchCache *cache,
@ -742,7 +742,7 @@ static void mesh_batch_cache_discard_uvedit_select(MeshBatchCache *cache)
void DRW_mesh_batch_cache_dirty_tag(Mesh *me, eMeshBatchDirtyMode mode)
{
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime.batch_cache);
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime->batch_cache);
if (cache == nullptr) {
return;
}
@ -830,7 +830,7 @@ static void mesh_batch_cache_free_subdiv_cache(MeshBatchCache *cache)
static void mesh_batch_cache_clear(Mesh *me)
{
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime.batch_cache);
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime->batch_cache);
if (!cache) {
return;
}
@ -862,7 +862,7 @@ static void mesh_batch_cache_clear(Mesh *me)
void DRW_mesh_batch_cache_free(Mesh *me)
{
mesh_batch_cache_clear(me);
MEM_SAFE_FREE(me->runtime.batch_cache);
MEM_SAFE_FREE(me->runtime->batch_cache);
}
/** \} */
@ -1017,7 +1017,7 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Object *object,
BLI_assert(gpumat_array_len == cache->mat_len);
mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed);
ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime.render_mutex;
ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime->render_mutex;
drw_attributes_merge(&cache->attr_needed, &attrs_needed, mesh_render_mutex);
mesh_batch_cache_request_surface_batches(cache);
return cache->surface_per_mat;
@ -1046,7 +1046,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Object *object, Mesh *me)
DRW_Attributes attrs_needed{};
request_active_and_default_color_attributes(*object, *me, attrs_needed);
ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime.render_mutex;
ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime->render_mutex;
drw_attributes_merge(&cache->attr_needed, &attrs_needed, mesh_render_mutex);
mesh_batch_cache_request_surface_batches(cache);
@ -1060,7 +1060,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Object *object, Mesh *me)
DRW_Attributes attrs_needed{};
request_active_and_default_color_attributes(*object, *me, attrs_needed);
ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime.render_mutex;
ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime->render_mutex;
drw_attributes_merge(&cache->attr_needed, &attrs_needed, mesh_render_mutex);
mesh_batch_cache_request_surface_batches(cache);
@ -1300,7 +1300,7 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_edges(Object *object, Mesh *me)
void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime)
{
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime.batch_cache);
MeshBatchCache *cache = static_cast<MeshBatchCache *>(me->runtime->batch_cache);
if (cache == nullptr) {
return;
@ -1446,7 +1446,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
}
}
ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime.render_mutex;
ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime->render_mutex;
/* Verify that all surface batches have needed attribute layers.
*/
@ -1537,7 +1537,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
const bool do_update_sculpt_normals = ob->sculpt && ob->sculpt->pbvh;
if (do_update_sculpt_normals) {
Mesh *mesh = static_cast<Mesh *>(ob->data);
BKE_pbvh_update_normals(ob->sculpt->pbvh, mesh->runtime.subdiv_ccg);
BKE_pbvh_update_normals(ob->sculpt->pbvh, mesh->runtime->subdiv_ccg);
}
cache->batch_ready |= batch_requested;
@ -1548,8 +1548,8 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
do_cage = editmesh_eval_final != editmesh_eval_cage;
do_uvcage = !(editmesh_eval_final->runtime.is_original_bmesh &&
editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH);
do_uvcage = !(editmesh_eval_final->runtime->is_original_bmesh &&
editmesh_eval_final->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH);
}
const bool do_subdivision = BKE_subsurf_modifier_has_gpu_subdiv(me);

View File

@ -2036,7 +2036,7 @@ static bool draw_subdiv_create_requested_buffers(Object *ob,
const bool use_hide,
OpenSubdiv_EvaluatorCache *evaluator_cache)
{
SubsurfRuntimeData *runtime_data = mesh->runtime.subsurf_runtime_data;
SubsurfRuntimeData *runtime_data = mesh->runtime->subsurf_runtime_data;
BLI_assert(runtime_data && runtime_data->has_gpu_subdiv);
if (runtime_data->settings.level == 0) {

View File

@ -1347,7 +1347,7 @@ static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd)
}
Mesh *mesh = static_cast<Mesh *>(scd->ob->data);
BKE_pbvh_update_normals(pbvh, mesh->runtime.subdiv_ccg);
BKE_pbvh_update_normals(pbvh, mesh->runtime->subdiv_ccg);
BKE_pbvh_draw_cb(pbvh,
update_only_visible,

View File

@ -15,6 +15,7 @@
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_unit.h"
#include "DNA_mesh_types.h"
@ -233,8 +234,8 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
float clip_planes[4][4];
/* allow for displaying shape keys and deform mods */
BMIter iter;
const float(*vert_coords)[3] = (me->runtime.edit_data ? me->runtime.edit_data->vertexCos :
nullptr);
const float(*vert_coords)[3] = (me->runtime->edit_data ? me->runtime->edit_data->vertexCos :
nullptr);
const bool use_coords = (vert_coords != nullptr);
/* when 2 or more edge-info options are enabled, space apart */
@ -339,8 +340,8 @@ void DRW_text_edit_mesh_measure_stats(ARegion *region,
const float(*poly_normals)[3] = nullptr;
if (use_coords) {
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
BKE_editmesh_cache_ensure_poly_normals(em, me->runtime.edit_data);
poly_normals = me->runtime.edit_data->polyNos;
BKE_editmesh_cache_ensure_poly_normals(em, me->runtime->edit_data);
poly_normals = me->runtime->edit_data->polyNos;
}
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {

View File

@ -16,6 +16,8 @@
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_mesh.h"
#include "draw_cache_extract.hh"
@ -116,7 +118,7 @@ BLI_INLINE const Mesh *editmesh_final_or_this(const Object *object, const Mesh *
BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me)
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_SUBD:
case ME_WRAPPER_TYPE_MDATA:
return &me->ldata;
@ -132,7 +134,7 @@ BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me)
BLI_INLINE const CustomData *mesh_cd_pdata_get_from_mesh(const Mesh *me)
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_SUBD:
case ME_WRAPPER_TYPE_MDATA:
return &me->pdata;
@ -148,7 +150,7 @@ BLI_INLINE const CustomData *mesh_cd_pdata_get_from_mesh(const Mesh *me)
BLI_INLINE const CustomData *mesh_cd_edata_get_from_mesh(const Mesh *me)
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_SUBD:
case ME_WRAPPER_TYPE_MDATA:
return &me->edata;
@ -164,7 +166,7 @@ BLI_INLINE const CustomData *mesh_cd_edata_get_from_mesh(const Mesh *me)
BLI_INLINE const CustomData *mesh_cd_vdata_get_from_mesh(const Mesh *me)
{
switch ((eMeshWrapperType)me->runtime.wrapper_type) {
switch (me->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_SUBD:
case ME_WRAPPER_TYPE_MDATA:
return &me->vdata;

View File

@ -557,7 +557,7 @@ static void extract_edituv_fdots_iter_poly_mesh(const MeshRenderData *mr,
const bool mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false;
if (mr->use_subsurf_fdots) {
const BLI_bitmap *facedot_tags = mr->me->runtime.subsurf_face_dot_tags;
const BLI_bitmap *facedot_tags = mr->me->runtime->subsurf_face_dot_tags;
const MLoop *mloop = mr->mloop;
const int ml_index_end = mp->loopstart + mp->totloop;

View File

@ -46,7 +46,7 @@ static void extract_fdots_iter_poly_mesh(const MeshRenderData *mr,
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata);
if (mr->use_subsurf_fdots) {
const BLI_bitmap *facedot_tags = mr->me->runtime.subsurf_face_dot_tags;
const BLI_bitmap *facedot_tags = mr->me->runtime->subsurf_face_dot_tags;
const MLoop *mloop = mr->mloop;
const int ml_index_end = mp->loopstart + mp->totloop;

View File

@ -77,7 +77,7 @@ static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr,
const MVert *mvert = mr->mvert;
const MLoop *mloop = mr->mloop;
const BLI_bitmap *facedot_tags = mr->me->runtime.subsurf_face_dot_tags;
const BLI_bitmap *facedot_tags = mr->me->runtime->subsurf_face_dot_tags;
const int ml_index_end = mp->loopstart + mp->totloop;
for (int ml_index = mp->loopstart; ml_index < ml_index_end; ml_index += 1) {

View File

@ -74,7 +74,7 @@ static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr,
void *_data)
{
MeshExtract_FdotUV_Data *data = static_cast<MeshExtract_FdotUV_Data *>(_data);
const BLI_bitmap *facedot_tags = mr->me->runtime.subsurf_face_dot_tags;
const BLI_bitmap *facedot_tags = mr->me->runtime->subsurf_face_dot_tags;
const MLoop *mloop = mr->mloop;
const int ml_index_end = mp->loopstart + mp->totloop;

View File

@ -22,7 +22,9 @@
#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_layer.h"
#include "BKE_mesh.h"
#include "BKE_report.h"
#include "WM_api.h"
@ -1065,8 +1067,8 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
{
Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(vc->depsgraph,
static_cast<ID *>(obedit->data));
if (me_eval->runtime.edit_data) {
coords = me_eval->runtime.edit_data->vertexCos;
if (me_eval->runtime->edit_data) {
coords = me_eval->runtime->edit_data->vertexCos;
}
}

View File

@ -597,6 +597,11 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo
* on it. Necessary to use the attribute API. */
strcpy(um->me.id.name, "MEundomesh_from_editmesh");
/* Runtime data is necessary for some asserts in other code, and the overhead of creating it for
* undo meshes should be low. */
BLI_assert(um->me.runtime == nullptr);
um->me.runtime = new blender::bke::MeshRuntime();
CustomData_MeshMasks cd_mask_extra{};
cd_mask_extra.vmask = CD_MASK_SHAPE_KEYINDEX;
BMeshToMeshParams params{};

View File

@ -3533,7 +3533,7 @@ static void PE_mirror_x(Depsgraph *depsgraph, Scene *scene, Object *ob, int tagg
}
const bool use_dm_final_indices = (psys->part->use_modifier_stack &&
!psmd_eval->mesh_final->runtime.deformed_only);
!BKE_mesh_is_deformed_only(psmd_eval->mesh_final));
/* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
BKE_mesh_tessface_ensure(me);
@ -4353,7 +4353,7 @@ static void brush_add_count_iter(void *__restrict iter_data_v,
0,
0,
0)) {
if (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only) {
if (psys->part->use_modifier_stack && !BKE_mesh_is_deformed_only(psmd_eval->mesh_final)) {
add_pars[iter].num = add_pars[iter].num_dmcache;
add_pars[iter].num_dmcache = DMCACHE_ISCHILD;
}
@ -4430,7 +4430,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
timestep = psys_get_timestep(&sim);
if (psys->part->use_modifier_stack || psmd_eval->mesh_final->runtime.deformed_only) {
if (psys->part->use_modifier_stack || BKE_mesh_is_deformed_only(psmd_eval->mesh_final)) {
mesh = psmd_eval->mesh_final;
}
else {

View File

@ -732,7 +732,7 @@ static bool remap_hair_emitter(Depsgraph *depsgraph,
invert_m4_m4(to_imat, to_mat);
const bool use_dm_final_indices = (target_psys->part->use_modifier_stack &&
!target_psmd->mesh_final->runtime.deformed_only);
!BKE_mesh_is_deformed_only(target_psmd->mesh_final));
if (use_dm_final_indices || !target_psmd->mesh_original) {
mesh = target_psmd->mesh_final;

View File

@ -4074,7 +4074,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
ps->totloop_eval = ps->me_eval->totloop;
ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
ps->totlooptri_eval = ps->me_eval->runtime.looptris.len;
ps->totlooptri_eval = BKE_mesh_runtime_looptri_len(ps->me_eval);
ps->poly_to_loop_uv = MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces");

View File

@ -286,7 +286,7 @@ static void imapaint_pick_uv(
const ePaintCanvasSource mode = scene->toolsettings->imapaint.mode;
const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval);
const int tottri = me_eval->runtime.looptris.len;
const int tottri = BKE_mesh_runtime_looptri_len(me_eval);
const MVert *mvert = BKE_mesh_verts(me_eval);
const MLoop *mloop = BKE_mesh_loops(me_eval);

View File

@ -40,6 +40,7 @@
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
@ -94,8 +95,8 @@ static bool stats_mesheval(const Mesh *me_eval, bool is_selected, SceneStats *st
int totvert, totedge, totface, totloop;
const SubdivCCG *subdiv_ccg = me_eval->runtime.subdiv_ccg;
const SubsurfRuntimeData *subsurf_runtime_data = me_eval->runtime.subsurf_runtime_data;
const SubdivCCG *subdiv_ccg = me_eval->runtime->subdiv_ccg;
const SubsurfRuntimeData *subsurf_runtime_data = me_eval->runtime->subsurf_runtime_data;
if (subdiv_ccg != nullptr) {
BKE_subdiv_ccg_topology_counters(subdiv_ccg, &totvert, &totedge, &totface, &totloop);

View File

@ -17,6 +17,7 @@
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_object.h"
#include "DEG_depsgraph.h"
@ -94,8 +95,8 @@ void ED_draw_object_facemap(Depsgraph *depsgraph,
const MPoly *mp;
int i;
if (me->runtime.looptris.array) {
const MLoopTri *mlt = me->runtime.looptris.array;
if (BKE_mesh_runtime_looptri_ensure(me)) {
const MLoopTri *mlt = BKE_mesh_runtime_looptri_ensure(me);
for (mp = polys, i = 0; i < mpoly_len; i++, mp++) {
if (facemap_data[i] == facemap) {
for (int j = 2; j < mp->totloop; j++) {

View File

@ -19,8 +19,10 @@
#include "BKE_context.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_global.h"
#include "BKE_layer.h"
#include "BKE_mesh.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@ -234,8 +236,8 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
Object *ob = gz_ele->bases[gz_ele->base_index]->object;
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, static_cast<ID *>(ob->data));
if (me_eval->runtime.edit_data) {
coords = me_eval->runtime.edit_data->vertexCos;
if (me_eval->runtime->edit_data) {
coords = me_eval->runtime->edit_data->vertexCos;
}
}
EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords);

View File

@ -576,7 +576,7 @@ void mesh_foreachScreenFace(
BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE);
if (me->runtime.subsurf_face_dot_tags != nullptr) {
if (me->runtime->subsurf_face_dot_tags != nullptr) {
BKE_mesh_foreach_mapped_subdiv_face_center(
me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP);
}

View File

@ -105,7 +105,7 @@ struct SnapData_EditMesh {
/* Looptris. */
BVHTreeFromEditMesh treedata_editmesh;
struct Mesh_Runtime *mesh_runtime;
blender::bke::MeshRuntime *mesh_runtime;
float min[3], max[3];
void clear()
@ -189,14 +189,14 @@ static const Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type,
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval);
if ((edit_mode_type == SNAP_GEOM_FINAL) && editmesh_eval_final) {
if (editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
if (editmesh_eval_final->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
return nullptr;
}
me_eval = editmesh_eval_final;
use_hide = true;
}
else if ((edit_mode_type == SNAP_GEOM_CAGE) && editmesh_eval_cage) {
if (editmesh_eval_cage->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) {
if (editmesh_eval_cage->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
return nullptr;
}
me_eval = editmesh_eval_cage;
@ -253,21 +253,21 @@ static SnapData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx,
sod = sod_p->get();
bool is_dirty = false;
if (sod->treedata_mesh.tree && sod->treedata_mesh.cached &&
!bvhcache_has_tree(me_eval->runtime.bvh_cache, sod->treedata_mesh.tree)) {
!bvhcache_has_tree(me_eval->runtime->bvh_cache, sod->treedata_mesh.tree)) {
/* The tree is owned by the Mesh and may have been freed since we last used. */
is_dirty = true;
}
else if (sod->bvhtree[0] && sod->cached[0] &&
!bvhcache_has_tree(me_eval->runtime.bvh_cache, sod->bvhtree[0])) {
!bvhcache_has_tree(me_eval->runtime->bvh_cache, sod->bvhtree[0])) {
/* The tree is owned by the Mesh and may have been freed since we last used. */
is_dirty = true;
}
else if (sod->bvhtree[1] && sod->cached[1] &&
!bvhcache_has_tree(me_eval->runtime.bvh_cache, sod->bvhtree[1])) {
!bvhcache_has_tree(me_eval->runtime->bvh_cache, sod->bvhtree[1])) {
/* The tree is owned by the Mesh and may have been freed since we last used. */
is_dirty = true;
}
else if (sod->treedata_mesh.looptri != me_eval->runtime.looptris.array) {
else if (sod->treedata_mesh.looptri != me_eval->looptris().data()) {
is_dirty = true;
}
else if (sod->treedata_mesh.vert != verts.data()) {
@ -330,19 +330,19 @@ static SnapData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx,
/* Searches for the #Mesh_Runtime associated with the object that is most likely to be updated due
* to changes in the `edit_mesh`. */
static Mesh_Runtime *snap_object_data_editmesh_runtime_get(Object *ob_eval)
static blender::bke::MeshRuntime *snap_object_data_editmesh_runtime_get(Object *ob_eval)
{
Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval);
if (editmesh_eval_final) {
return &editmesh_eval_final->runtime;
return editmesh_eval_final->runtime;
}
Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval);
if (editmesh_eval_cage) {
return &editmesh_eval_cage->runtime;
return editmesh_eval_cage->runtime;
}
return &((Mesh *)ob_eval->data)->runtime;
return ((Mesh *)ob_eval->data)->runtime;
}
static SnapData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,

View File

@ -1953,8 +1953,6 @@ static LineartEdgeNeighbor *lineart_build_edge_neighbor(Mesh *me, int total_edge
LineartEdgeNeighbor *edge_nabr = MEM_mallocN(sizeof(LineartEdgeNeighbor) * total_edges,
"LineartEdgeNeighbor arr");
MLoopTri *mlooptri = me->runtime.looptris.array;
TaskParallelSettings en_settings;
BLI_parallel_range_settings_defaults(&en_settings);
/* Set the minimum amount of edges a thread has to process. */
@ -1963,7 +1961,7 @@ static LineartEdgeNeighbor *lineart_build_edge_neighbor(Mesh *me, int total_edge
EdgeNeighborData en_data;
en_data.adj_e = adj_e;
en_data.edge_nabr = edge_nabr;
en_data.mlooptri = mlooptri;
en_data.mlooptri = BKE_mesh_runtime_looptri_ensure(me);
en_data.mloop = BKE_mesh_loops(me);
BLI_task_parallel_range(0, total_edges, &en_data, lineart_edge_neighbor_init_task, &en_settings);

View File

@ -19,10 +19,14 @@ namespace blender {
template<typename T> class Span;
template<typename T> class MutableSpan;
namespace bke {
struct MeshRuntime;
class AttributeAccessor;
class MutableAttributeAccessor;
} // namespace bke
} // namespace blender
using MeshRuntimeHandle = blender::bke::MeshRuntime;
#else
typedef struct MeshRuntimeHandle MeshRuntimeHandle;
#endif
#ifdef __cplusplus
@ -30,133 +34,14 @@ extern "C" {
#endif
struct AnimData;
struct BVHCache;
struct Ipo;
struct Key;
struct MCol;
struct MEdge;
struct MFace;
struct MLoopCol;
struct MLoopTri;
struct MVert;
struct Material;
struct Mesh;
struct SubdivCCG;
struct SubsurfRuntimeData;
#
#
typedef struct EditMeshData {
/** when set, \a vertexNos, polyNos are lazy initialized */
const float (*vertexCos)[3];
/** lazy initialize (when \a vertexCos is set) */
float const (*vertexNos)[3];
float const (*polyNos)[3];
/** also lazy init but don't depend on \a vertexCos */
const float (*polyCos)[3];
} EditMeshData;
/**
* \warning Typical access is done via
* #BKE_mesh_runtime_looptri_ensure, #BKE_mesh_runtime_looptri_len.
*/
struct MLoopTri_Store {
DNA_DEFINE_CXX_METHODS(MLoopTri_Store)
/* WARNING! swapping between array (ready-to-be-used data) and array_wip
* (where data is actually computed)
* shall always be protected by same lock as one used for looptris computing. */
struct MLoopTri *array, *array_wip;
int len;
int len_alloc;
};
/** Runtime data, not saved in files. */
typedef struct Mesh_Runtime {
DNA_DEFINE_CXX_METHODS(Mesh_Runtime)
/* Evaluated mesh for objects which do not have effective modifiers.
* This mesh is used as a result of modifier stack evaluation.
* Since modifier stack evaluation is threaded on object level we need some synchronization. */
struct Mesh *mesh_eval;
void *eval_mutex;
/* A separate mutex is needed for normal calculation, because sometimes
* the normals are needed while #eval_mutex is already locked. */
void *normals_mutex;
/** Needed to ensure some thread-safety during render data pre-processing. */
void *render_mutex;
/** Lazily initialized SoA data from the #edit_mesh field in #Mesh. */
struct EditMeshData *edit_data;
/**
* Data used to efficiently draw the mesh in the viewport, especially useful when
* the same mesh is used in many objects or instances. See `draw_cache_impl_mesh.cc`.
*/
void *batch_cache;
/** Cache for derived triangulation of the mesh. */
struct MLoopTri_Store looptris;
/** Cache for BVH trees generated for the mesh. Defined in 'BKE_bvhutil.c' */
struct BVHCache *bvh_cache;
/** Cache of non-manifold boundary data for Shrinkwrap Target Project. */
struct ShrinkwrapBoundaryData *shrinkwrap_data;
/** Needed in case we need to lazily initialize the mesh. */
CustomData_MeshMasks cd_mask_extra;
struct SubdivCCG *subdiv_ccg;
int subdiv_ccg_tot_level;
/** Set by modifier stack if only deformed from original. */
char deformed_only;
/**
* Copied from edit-mesh (hint, draw with edit-mesh data when true).
*
* Modifiers that edit the mesh data in-place must set this to false
* (most #eModifierTypeType_NonGeometrical modifiers). Otherwise the edit-mesh
* data will be used for drawing, missing changes from modifiers. See T79517.
*/
char is_original_bmesh;
/** #eMeshWrapperType and others. */
char wrapper_type;
/**
* A type mask from wrapper_type,
* in case there are differences in finalizing logic between types.
*/
char wrapper_type_finalize;
/**
* Settings for lazily evaluating the subdivision on the CPU if needed. These are
* set in the modifier when GPU subdivision can be performed, and owned by the by
* the modifier in the object.
*/
struct SubsurfRuntimeData *subsurf_runtime_data;
void *_pad1;
/**
* Caches for lazily computed vertex and polygon normals. These are stored here rather than in
* #CustomData because they can be calculated on a const mesh, and adding custom data layers on a
* const mesh is not thread-safe.
*/
char _pad2[6];
char vert_normals_dirty;
char poly_normals_dirty;
float (*vert_normals)[3];
float (*poly_normals)[3];
/**
* A #BLI_bitmap containing tags for the center vertices of subdivided polygons, set by the
* subdivision surface modifier and used by drawing code instead of polygon center face dots.
*/
uint32_t *subsurf_face_dot_tags;
} Mesh_Runtime;
typedef struct Mesh {
DNA_DEFINE_CXX_METHODS(Mesh)
@ -316,9 +201,13 @@ typedef struct Mesh {
char _pad1[4];
void *_pad2;
Mesh_Runtime runtime;
/**
* Data that isn't saved in files, including caches of derived data, temporary data to improve
* the editing experience, etc. Runtime data is created when reading files and can be accessed
* without null checks, with the exception of some temporary meshes which should allocate and
* free the data if they are passed to functions that expect run-time data.
*/
MeshRuntimeHandle *runtime;
#ifdef __cplusplus
/**
* Array of vertex positions (and various other data). Edges and faces are defined by indices
@ -383,16 +272,6 @@ typedef struct TFace {
/* **************** MESH ********************* */
/** #Mesh_Runtime.wrapper_type */
typedef enum eMeshWrapperType {
/** Use mesh data (#Mesh.mvert, #Mesh.medge, #Mesh.mloop, #Mesh.mpoly). */
ME_WRAPPER_TYPE_MDATA = 0,
/** Use edit-mesh data (#Mesh.edit_mesh, #Mesh_Runtime.edit_data). */
ME_WRAPPER_TYPE_BMESH = 1,
/** Use subdivision mesh data (#Mesh_Runtime.mesh_eval). */
ME_WRAPPER_TYPE_SUBD = 2,
} eMeshWrapperType;
/** #Mesh.texflag */
enum {
ME_AUTOSPACE = 1,

View File

@ -406,12 +406,39 @@ static int rna_MeshLoopTriangle_index_get(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
const MLoopTri *ltri = (MLoopTri *)ptr->data;
const int index = (int)(ltri - mesh->runtime.looptris.array);
const int index = (int)(ltri - BKE_mesh_runtime_looptri_ensure(mesh));
BLI_assert(index >= 0);
BLI_assert(index < mesh->runtime.looptris.len);
BLI_assert(index < BKE_mesh_runtime_looptri_len(mesh));
return index;
}
static void rna_Mesh_loop_triangles_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
const MLoopTri *looptris = BKE_mesh_runtime_looptri_ensure(mesh);
rna_iterator_array_begin(
iter, (void *)looptris, sizeof(MLoopTri), BKE_mesh_runtime_looptri_len(mesh), false, NULL);
}
static int rna_Mesh_loop_triangles_length(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
return BKE_mesh_runtime_looptri_len(mesh);
}
int rna_Mesh_loop_triangles_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr)
{
const Mesh *mesh = rna_mesh(ptr);
if (index < 0 || index >= BKE_mesh_runtime_looptri_len(mesh)) {
return false;
}
/* Casting away const is okay because this RNA type doesn't allow changing the value. */
r_ptr->owner_id = (ID *)&mesh->id;
r_ptr->type = &RNA_MeshLoopTriangle;
r_ptr->data = (void *)&BKE_mesh_runtime_looptri_ensure(mesh)[index];
return true;
}
static void rna_MeshVertex_normal_get(PointerRNA *ptr, float *value)
{
Mesh *mesh = rna_mesh(ptr);
@ -1502,8 +1529,9 @@ static char *rna_MeshPolygon_path(const PointerRNA *ptr)
static char *rna_MeshLoopTriangle_path(const PointerRNA *ptr)
{
return BLI_sprintfN("loop_triangles[%d]",
(int)((MLoopTri *)ptr->data - rna_mesh(ptr)->runtime.looptris.array));
return BLI_sprintfN(
"loop_triangles[%d]",
(int)((MLoopTri *)ptr->data - BKE_mesh_runtime_looptri_ensure(rna_mesh(ptr))));
}
static char *rna_MeshEdge_path(const PointerRNA *ptr)
@ -3684,7 +3712,15 @@ static void rna_def_mesh(BlenderRNA *brna)
NULL);
prop = RNA_def_property(srna, "loop_triangles", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "runtime.looptris.array", "runtime.looptris.len");
RNA_def_property_collection_funcs(prop,
"rna_Mesh_loop_triangles_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_iterator_array_get",
"rna_Mesh_loop_triangles_length",
"rna_Mesh_loop_triangles_lookup_int",
NULL,
NULL);
RNA_def_property_struct_type(prop, "MeshLoopTriangle");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_ui_text(prop, "Loop Triangles", "Tessellation of mesh polygons into triangles");

View File

@ -23,6 +23,7 @@
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_mesh_wrapper.h"
#include "BKE_modifier.h"
#include "BKE_screen.h"
@ -494,7 +495,7 @@ static void deformVertsEM(ModifierData *md,
mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, verts_num, false);
}
if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
if (mesh && BKE_mesh_wrapper_type(mesh) == ME_WRAPPER_TYPE_MDATA) {
BLI_assert(mesh->totvert == verts_num);
}

View File

@ -213,7 +213,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
dtmd->defgrp_name,
invert_vgroup,
&reports)) {
result->runtime.is_original_bmesh = false;
result->runtime->is_original_bmesh = false;
}
if (BKE_reports_contain(&reports, RPT_ERROR)) {

View File

@ -230,7 +230,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
if ((ctx->object->mode & OB_MODE_SCULPT) && !for_orco && !for_render && !sculpt_base_mesh) {
/* NOTE: CCG takes ownership over Subdiv. */
result = multires_as_ccg(mmd, ctx, mesh, subdiv);
result->runtime.subdiv_ccg_tot_level = mmd->totlvl;
result->runtime->subdiv_ccg_tot_level = mmd->totlvl;
/* TODO(sergey): Usually it is sculpt stroke's update variants which
* takes care of this, but is possible that we need this before the
* stroke: i.e. when exiting blender right after stroke is done.
@ -238,7 +238,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
* surely there is a better way of solving this. */
if (ctx->object->sculpt != nullptr) {
SculptSession *sculpt_session = ctx->object->sculpt;
sculpt_session->subdiv_ccg = result->runtime.subdiv_ccg;
sculpt_session->subdiv_ccg = result->runtime->subdiv_ccg;
sculpt_session->multires.active = true;
sculpt_session->multires.modifier = mmd;
sculpt_session->multires.level = mmd->sculptlvl;

View File

@ -623,7 +623,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
MEM_SAFE_FREE(loopnors);
result->runtime.is_original_bmesh = false;
result->runtime->is_original_bmesh = false;
return result;
}

View File

@ -159,7 +159,7 @@ static void deformVerts(ModifierData *md,
BKE_mesh_tessface_ensure(psmd->mesh_final);
if (!psmd->mesh_final->runtime.deformed_only) {
if (!psmd->mesh_final->runtime->deformed_only) {
/* Get the original mesh from the object, this is what the particles
* are attached to so in case of non-deform modifiers we need to remap
* them to the final mesh (typically subdivision surfaces). */

View File

@ -67,10 +67,9 @@ static void init_dualcon_mesh(DualConInput *input, Mesh *mesh)
input->mloop = (void *)BKE_mesh_loops(mesh);
input->loop_stride = sizeof(MLoop);
BKE_mesh_runtime_looptri_ensure(mesh);
input->looptri = (void *)mesh->runtime.looptris.array;
input->looptri = (void *)BKE_mesh_runtime_looptri_ensure(mesh);
input->tri_stride = sizeof(MLoopTri);
input->tottri = mesh->runtime.looptris.len;
input->tottri = BKE_mesh_runtime_looptri_len(mesh);
INIT_MINMAX(input->min, input->max);
BKE_mesh_minmax(mesh, input->min, input->max);

View File

@ -208,7 +208,7 @@ static void subdiv_cache_mesh_wrapper_settings(const ModifierEvalContext *ctx,
runtime_data->calc_loop_normals = false; /* Set at the end of modifier stack evaluation. */
runtime_data->use_loop_normals = (smd->flags & eSubsurfModifierFlag_UseCustomNormals);
mesh->runtime.subsurf_runtime_data = runtime_data;
mesh->runtime->subsurf_runtime_data = runtime_data;
}
/* Modifier itself. */

View File

@ -188,7 +188,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
&mesh_prior_modifiers->id,
nullptr,
(LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_CD_REFERENCE));
mesh->runtime.deformed_only = 1;
mesh->runtime->deformed_only = 1;
}
if (em != nullptr) {
@ -218,7 +218,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
}
}
if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) {
if (mesh && mesh->runtime->wrapper_type == ME_WRAPPER_TYPE_MDATA) {
BLI_assert(mesh->totvert == verts_num);
}

View File

@ -283,7 +283,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
}
}
mesh->runtime.is_original_bmesh = false;
mesh->runtime->is_original_bmesh = false;
return mesh;
}

View File

@ -216,7 +216,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
settings.use_threading = (polys_num > 1000);
BLI_task_parallel_range(0, polys_num, &data, uv_warp_compute, &settings);
mesh->runtime.is_original_bmesh = false;
mesh->runtime->is_original_bmesh = false;
return mesh;
}

View File

@ -21,6 +21,7 @@
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_cache.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_mesh.h"
@ -337,7 +338,7 @@ static void deformVertsEM(ModifierData *md,
if (!ELEM(mesh_src, nullptr, mesh)) {
/* Important not to free `vertexCos` owned by the caller. */
EditMeshData *edit_data = mesh_src->runtime.edit_data;
EditMeshData *edit_data = mesh_src->runtime->edit_data;
if (edit_data->vertexCos == vertexCos) {
edit_data->vertexCos = nullptr;
}

View File

@ -676,7 +676,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
MEM_SAFE_FREE(wn_data.mode_pair);
MEM_SAFE_FREE(wn_data.items_data);
result->runtime.is_original_bmesh = false;
result->runtime->is_original_bmesh = false;
return result;
}

View File

@ -278,7 +278,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
MEM_freeN(new_w);
MEM_freeN(dw);
mesh->runtime.is_original_bmesh = false;
mesh->runtime->is_original_bmesh = false;
/* Return the vgroup-modified mesh. */
return mesh;

View File

@ -438,7 +438,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
MEM_freeN(dw2);
MEM_SAFE_FREE(indices);
mesh->runtime.is_original_bmesh = false;
mesh->runtime->is_original_bmesh = false;
/* Return the vgroup-modified mesh. */
return mesh;

View File

@ -639,7 +639,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
TIMEIT_END(perf);
#endif
mesh->runtime.is_original_bmesh = false;
mesh->runtime->is_original_bmesh = false;
/* Return the vgroup-modified mesh. */
return mesh;

View File

@ -590,7 +590,7 @@ bool RE_bake_pixels_populate_from_objects(struct Mesh *me_low,
me_highpoly[i] = highpoly[i].me;
BKE_mesh_runtime_looptri_ensure(me_highpoly[i]);
if (me_highpoly[i]->runtime.looptris.len != 0) {
if (BKE_mesh_runtime_looptri_len(me_highpoly[i]) != 0) {
/* Create a BVH-tree for each `highpoly` object. */
BKE_bvhtree_from_mesh_get(&treeData[i], me_highpoly[i], BVHTREE_FROM_LOOPTRI, 2);