Blender  V3.3
cdderivedmesh.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2006 Blender Foundation. All rights reserved. */
3 
10 #include "atomic_ops.h"
11 
12 #include "BLI_math.h"
13 #include "BLI_utildefines.h"
14 
15 #include "BKE_DerivedMesh.h"
16 #include "BKE_cdderivedmesh.h"
17 #include "BKE_curve.h"
18 #include "BKE_editmesh.h"
19 #include "BKE_mesh.h"
20 #include "BKE_mesh_mapping.h"
21 #include "BKE_object.h"
22 #include "BKE_paint.h"
23 #include "BKE_pbvh.h"
24 
25 #include "DNA_curve_types.h" /* for Curve */
26 #include "DNA_mesh_types.h"
27 #include "DNA_meshdata_types.h"
28 #include "DNA_object_types.h"
29 
30 #include "MEM_guardedalloc.h"
31 
32 #include <limits.h>
33 #include <math.h>
34 #include <string.h>
35 
36 typedef struct {
38 
39  /* these point to data in the DerivedMesh custom data layers,
40  * they are only here for efficiency and convenience */
42  const float (*vert_normals)[3];
47 
48  /* Cached */
49  struct PBVH *pbvh;
50  bool pbvh_draw;
51 
52  /* Mesh connectivity */
54  int *pmap_mem;
56 
57 /**************** DerivedMesh interface functions ****************/
59 {
60  return dm->numVertData;
61 }
62 
64 {
65  return dm->numEdgeData;
66 }
67 
69 {
70  return dm->numLoopData;
71 }
72 
74 {
75  return dm->numPolyData;
76 }
77 
78 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
79 {
80  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
81  memcpy(r_vert, cddm->mvert, sizeof(*r_vert) * dm->numVertData);
82 }
83 
84 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
85 {
86  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
87  memcpy(r_edge, cddm->medge, sizeof(*r_edge) * dm->numEdgeData);
88 }
89 
90 static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
91 {
92  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
93  memcpy(r_loop, cddm->mloop, sizeof(*r_loop) * dm->numLoopData);
94 }
95 
96 static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
97 {
98  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
99  memcpy(r_poly, cddm->mpoly, sizeof(*r_poly) * dm->numPolyData);
100 }
101 
102 static void cdDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
103 {
104  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
105 
106  copy_v3_v3(r_co, cddm->mvert[index].co);
107 }
108 
109 static void cdDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
110 {
111  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
112  copy_v3_v3(r_no, cddm->vert_normals[index]);
113 }
114 
116 {
117  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
118  const unsigned int totpoly = dm->numPolyData;
119  const unsigned int totloop = dm->numLoopData;
120 
122  BLI_assert(totpoly == 0 || cddm->dm.looptris.array_wip != NULL);
123 
125  cddm->mloop, cddm->mpoly, cddm->mvert, totloop, totpoly, cddm->dm.looptris.array_wip);
126 
127  BLI_assert(cddm->dm.looptris.array == NULL);
129  (void **)&cddm->dm.looptris.array, cddm->dm.looptris.array, cddm->dm.looptris.array_wip);
130  cddm->dm.looptris.array_wip = NULL;
131 }
132 
134 {
135  if (cddm->pmap) {
136  MEM_freeN(cddm->pmap);
137  }
138  if (cddm->pmap_mem) {
139  MEM_freeN(cddm->pmap_mem);
140  }
141 }
142 
143 static void cdDM_release(DerivedMesh *dm)
144 {
145  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
146 
147  if (DM_release(dm)) {
148  cdDM_free_internal(cddm);
149  MEM_freeN(cddm);
150  }
151 }
152 
153 /**************** CDDM interface functions ****************/
154 static CDDerivedMesh *cdDM_create(const char *desc)
155 {
156  CDDerivedMesh *cddm;
157  DerivedMesh *dm;
158 
159  cddm = MEM_callocN(sizeof(*cddm), desc);
160  dm = &cddm->dm;
161 
166 
171 
174 
176 
179 
180  dm->release = cdDM_release;
181 
182  return cddm;
183 }
184 
186  eCDAllocType alloctype,
187  const CustomData_MeshMasks *mask)
188 {
189  CDDerivedMesh *cddm = cdDM_create(__func__);
190  DerivedMesh *dm = &cddm->dm;
191  CustomData_MeshMasks cddata_masks = *mask;
192 
193  cddata_masks.lmask &= ~CD_MASK_MDISPS;
194 
195  /* this does a referenced copy, with an exception for fluidsim */
196 
197  DM_init(dm,
198  DM_TYPE_CDDM,
199  mesh->totvert,
200  mesh->totedge,
201  0 /* mesh->totface */,
202  mesh->totloop,
203  mesh->totpoly);
204 
205  /* This should actually be dm->deformedOnly = mesh->runtime.deformed_only,
206  * but only if the original mesh had its deformed_only flag correctly set
207  * (which isn't generally the case). */
208  dm->deformedOnly = 1;
209  dm->cd_flag = mesh->cd_flag;
210 
211  CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, alloctype, mesh->totvert);
212  CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, alloctype, mesh->totedge);
214  &dm->faceData,
215  cddata_masks.fmask | CD_MASK_ORIGINDEX,
216  alloctype,
217  0 /* mesh->totface */);
218  CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, alloctype, mesh->totloop);
219  CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, alloctype, mesh->totpoly);
220 
222  /* Though this may be an unnecessary calculation, simply retrieving the layer may return nothing
223  * or dirty normals. */
228 #if 0
230 #else
231  cddm->mface = NULL;
232 #endif
233 
234  /* commented since even when CD_ORIGINDEX was first added this line fails
235  * on the default cube, (after editmode toggle too) - campbell */
236 #if 0
238 #endif
239 
240  return dm;
241 }
242 
244 {
246 }
247 
249 {
250  CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
251  DerivedMesh *dm = &cddm->dm;
252  int numVerts = source->numVertData;
253  int numEdges = source->numEdgeData;
254  int numTessFaces = 0;
255  int numLoops = source->numLoopData;
256  int numPolys = source->numPolyData;
257 
258  /* NOTE: Don't copy tessellation faces if not requested explicitly. */
259 
260  /* ensure these are created if they are made on demand */
261  source->getVertDataArray(source, CD_ORIGINDEX);
262  source->getEdgeDataArray(source, CD_ORIGINDEX);
263  source->getPolyDataArray(source, CD_ORIGINDEX);
264 
265  /* this initializes dm, and copies all non mvert/medge/mface layers */
266  DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys);
267  dm->deformedOnly = source->deformedOnly;
268  dm->cd_flag = source->cd_flag;
269 
270  CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
271  CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
272 
273  /* now add mvert/medge/mface layers */
274  cddm->mvert = source->dupVertArray(source);
275  cddm->medge = source->dupEdgeArray(source);
276 
277  CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
278  CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
279 
280  DM_DupPolys(source, dm);
281 
284 
285  return dm;
286 }
typedef float(TangentPoint)[2]
void * DM_get_edge_data_layer(struct DerivedMesh *dm, int type)
Definition: DerivedMesh.cc:441
void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys)
Definition: DerivedMesh.cc:250
bool DM_release(DerivedMesh *dm)
Definition: DerivedMesh.cc:307
void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys)
Definition: DerivedMesh.cc:277
void DM_ensure_looptri_data(DerivedMesh *dm)
Definition: DerivedMesh.cc:362
void * DM_get_vert_data_layer(struct DerivedMesh *dm, int type)
Definition: DerivedMesh.cc:432
void DM_DupPolys(DerivedMesh *source, DerivedMesh *target)
Definition: DerivedMesh.cc:332
@ DM_TYPE_CDDM
bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
eCDAllocType
@ CD_REFERENCE
@ CD_ASSIGN
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_get_layer(const struct CustomData *data, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.cc:2776
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
const CustomData_MeshMasks CD_MASK_MESH
Definition: customdata.cc:2065
const float(* BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3]
void BKE_mesh_recalc_looptri(const struct MLoop *mloop, const struct MPoly *mpoly, const struct MVert *mvert, int totloop, int totpoly, struct MLoopTri *mlooptri)
General operations, lookup, etc. for blender objects.
A BVH for high poly meshes.
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define CD_MASK_ORIGINDEX
@ CD_MFACE
@ CD_ORIGINDEX
@ CD_MEDGE
@ CD_MVERT
#define CD_MASK_MDISPS
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE void * atomic_cas_ptr(void **v, void *old, void *_new)
static DerivedMesh * cdDM_from_mesh_ex(Mesh *mesh, eCDAllocType alloctype, const CustomData_MeshMasks *mask)
static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
Definition: cdderivedmesh.c:84
static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
Definition: cdderivedmesh.c:90
static void cdDM_recalc_looptri(DerivedMesh *dm)
static int cdDM_getNumLoops(DerivedMesh *dm)
Definition: cdderivedmesh.c:68
static void cdDM_free_internal(CDDerivedMesh *cddm)
static CDDerivedMesh * cdDM_create(const char *desc)
static void cdDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
static void cdDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
Definition: cdderivedmesh.c:78
static int cdDM_getNumVerts(DerivedMesh *dm)
Definition: cdderivedmesh.c:58
static int cdDM_getNumEdges(DerivedMesh *dm)
Definition: cdderivedmesh.c:63
DerivedMesh * CDDM_from_mesh(Mesh *mesh)
static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
Definition: cdderivedmesh.c:96
static void cdDM_release(DerivedMesh *dm)
static void cdDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
DerivedMesh * CDDM_copy(DerivedMesh *source)
static int cdDM_getNumPolys(DerivedMesh *dm)
Definition: cdderivedmesh.c:73
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
struct PBVH * pbvh
Definition: cdderivedmesh.c:49
DerivedMesh dm
Definition: cdderivedmesh.c:37
const float(* vert_normals)[3]
Definition: cdderivedmesh.c:42
MeshElemMap * pmap
Definition: cdderivedmesh.c:53
CustomData faceData
void(* getVertNo)(DerivedMesh *dm, int index, float r_no[3])
void *(* getVertDataArray)(DerivedMesh *dm, int type)
CustomData vertData
void(* copyLoopArray)(DerivedMesh *dm, struct MLoop *r_loop)
void(* copyEdgeArray)(DerivedMesh *dm, struct MEdge *r_edge)
int(* getNumVerts)(DerivedMesh *dm)
void(* copyPolyArray)(DerivedMesh *dm, struct MPoly *r_poly)
int(* getNumPolys)(DerivedMesh *dm)
struct MEdge *(* dupEdgeArray)(DerivedMesh *dm)
int(* getNumEdges)(DerivedMesh *dm)
struct DerivedMesh::@16 looptris
CustomData polyData
struct MVert *(* dupVertArray)(DerivedMesh *dm)
struct MLoopTri * array_wip
void(* copyVertArray)(DerivedMesh *dm, struct MVert *r_vert)
void *(* getPolyDataArray)(DerivedMesh *dm, int type)
void *(* getEdgeDataArray)(DerivedMesh *dm, int type)
CustomData edgeData
CustomData loopData
void(* recalcLoopTri)(DerivedMesh *dm)
struct MLoopTri * array
void(* release)(DerivedMesh *dm)
void(* getVertCo)(DerivedMesh *dm, int index, float r_co[3])
int(* getNumLoops)(DerivedMesh *dm)
float co[3]
CustomData vdata
int totedge
char cd_flag
int totvert
CustomData pdata
CustomData fdata
int totpoly
CustomData edata
int totloop
CustomData ldata