Blender  V2.93
cdderivedmesh.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2006 Blender Foundation.
17  * All rights reserved.
18  * Implementation of CDDerivedMesh.
19  *
20  * BKE_cdderivedmesh.h contains the function prototypes for this file.
21  */
22 
27 #include "atomic_ops.h"
28 
29 #include "BLI_math.h"
30 #include "BLI_utildefines.h"
31 
32 #include "BKE_DerivedMesh.h"
33 #include "BKE_cdderivedmesh.h"
34 #include "BKE_curve.h"
35 #include "BKE_editmesh.h"
36 #include "BKE_mesh.h"
37 #include "BKE_mesh_mapping.h"
38 #include "BKE_object.h"
39 #include "BKE_paint.h"
40 #include "BKE_pbvh.h"
41 
42 #include "DNA_curve_types.h" /* for Curve */
43 #include "DNA_mesh_types.h"
44 #include "DNA_meshdata_types.h"
45 #include "DNA_object_types.h"
46 
47 #include "MEM_guardedalloc.h"
48 
49 #include <limits.h>
50 #include <math.h>
51 #include <string.h>
52 
53 typedef struct {
55 
56  /* these point to data in the DerivedMesh custom data layers,
57  * they are only here for efficiency and convenience */
63 
64  /* Cached */
65  struct PBVH *pbvh;
66  bool pbvh_draw;
67 
68  /* Mesh connectivity */
70  int *pmap_mem;
72 
73 /**************** DerivedMesh interface functions ****************/
75 {
76  return dm->numVertData;
77 }
78 
80 {
81  return dm->numEdgeData;
82 }
83 
85 {
86  /* uncomment and add a breakpoint on the printf()
87  * to help debug tessfaces issues since BMESH merge. */
88 #if 0
89  if (dm->numTessFaceData == 0 && dm->numPolyData != 0) {
90  printf("%s: has no faces!\n");
91  }
92 #endif
93  return dm->numTessFaceData;
94 }
95 
97 {
98  return dm->numLoopData;
99 }
100 
102 {
103  return dm->numPolyData;
104 }
105 
106 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *r_vert)
107 {
108  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
109  *r_vert = cddm->mvert[index];
110 }
111 
112 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *r_edge)
113 {
114  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
115  *r_edge = cddm->medge[index];
116 }
117 
118 static void cdDM_getTessFace(DerivedMesh *dm, int index, MFace *r_face)
119 {
120  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
121  *r_face = cddm->mface[index];
122 }
123 
124 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
125 {
126  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
127  memcpy(r_vert, cddm->mvert, sizeof(*r_vert) * dm->numVertData);
128 }
129 
130 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
131 {
132  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
133  memcpy(r_edge, cddm->medge, sizeof(*r_edge) * dm->numEdgeData);
134 }
135 
136 static void cdDM_copyTessFaceArray(DerivedMesh *dm, MFace *r_face)
137 {
138  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
139  memcpy(r_face, cddm->mface, sizeof(*r_face) * dm->numTessFaceData);
140 }
141 
142 static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
143 {
144  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
145  memcpy(r_loop, cddm->mloop, sizeof(*r_loop) * dm->numLoopData);
146 }
147 
148 static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
149 {
150  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
151  memcpy(r_poly, cddm->mpoly, sizeof(*r_poly) * dm->numPolyData);
152 }
153 
154 static void cdDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
155 {
156  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
157 
158  copy_v3_v3(r_co, cddm->mvert[index].co);
159 }
160 
161 static void cdDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
162 {
163  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
164  normal_short_to_float_v3(r_no, cddm->mvert[index].no);
165 }
166 
168 {
169  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
170 
171  if (!cddm->pmap && ob->type == OB_MESH) {
172  Mesh *me = ob->data;
173 
175  &cddm->pmap, &cddm->pmap_mem, me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
176  }
177 
178  return cddm->pmap;
179 }
180 
182 {
183  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
184  const unsigned int totpoly = dm->numPolyData;
185  const unsigned int totloop = dm->numLoopData;
186 
188  BLI_assert(totpoly == 0 || cddm->dm.looptris.array_wip != NULL);
189 
191  cddm->mloop, cddm->mpoly, cddm->mvert, totloop, totpoly, cddm->dm.looptris.array_wip);
192 
193  BLI_assert(cddm->dm.looptris.array == NULL);
195  (void **)&cddm->dm.looptris.array, cddm->dm.looptris.array, cddm->dm.looptris.array_wip);
196  cddm->dm.looptris.array_wip = NULL;
197 }
198 
200 {
201  if (cddm->pmap) {
202  MEM_freeN(cddm->pmap);
203  }
204  if (cddm->pmap_mem) {
205  MEM_freeN(cddm->pmap_mem);
206  }
207 }
208 
209 static void cdDM_release(DerivedMesh *dm)
210 {
211  CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
212 
213  if (DM_release(dm)) {
214  cdDM_free_internal(cddm);
215  MEM_freeN(cddm);
216  }
217 }
218 
219 /**************** CDDM interface functions ****************/
220 static CDDerivedMesh *cdDM_create(const char *desc)
221 {
222  CDDerivedMesh *cddm;
223  DerivedMesh *dm;
224 
225  cddm = MEM_callocN(sizeof(*cddm), desc);
226  dm = &cddm->dm;
227 
233 
234  dm->getVert = cdDM_getVert;
235  dm->getEdge = cdDM_getEdge;
237 
243 
250 
252 
255 
257 
258  dm->release = cdDM_release;
259 
260  return cddm;
261 }
262 
264  eCDAllocType alloctype,
265  const CustomData_MeshMasks *mask)
266 {
267  CDDerivedMesh *cddm = cdDM_create(__func__);
268  DerivedMesh *dm = &cddm->dm;
269  CustomData_MeshMasks cddata_masks = *mask;
270 
271  cddata_masks.lmask &= ~CD_MASK_MDISPS;
272 
273  /* this does a referenced copy, with an exception for fluidsim */
274 
275  DM_init(dm,
276  DM_TYPE_CDDM,
277  mesh->totvert,
278  mesh->totedge,
279  0 /* mesh->totface */,
280  mesh->totloop,
281  mesh->totpoly);
282 
283  /* This should actually be dm->deformedOnly = mesh->runtime.deformed_only,
284  * but only if the original mesh had its deformed_only flag correctly set
285  * (which isn't generally the case). */
286  dm->deformedOnly = 1;
287  dm->cd_flag = mesh->cd_flag;
288 
290  dm->dirty |= DM_DIRTY_NORMALS;
291  }
292  /* TODO DM_DIRTY_TESS_CDLAYERS ? Maybe not though,
293  * since we probably want to switch to looptris? */
294 
295  CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, alloctype, mesh->totvert);
296  CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, alloctype, mesh->totedge);
298  &dm->faceData,
299  cddata_masks.fmask | CD_MASK_ORIGINDEX,
300  alloctype,
301  0 /* mesh->totface */);
302  CustomData_merge(&mesh->ldata, &dm->loopData, cddata_masks.lmask, alloctype, mesh->totloop);
303  CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, alloctype, mesh->totpoly);
304 
309 #if 0
311 #else
312  cddm->mface = NULL;
313 #endif
314 
315  /* commented since even when CD_ORIGINDEX was first added this line fails
316  * on the default cube, (after editmode toggle too) - campbell */
317 #if 0
319 #endif
320 
321  return dm;
322 }
323 
325 {
327 }
328 
330 {
331  CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
332  DerivedMesh *dm = &cddm->dm;
333  int numVerts = source->numVertData;
334  int numEdges = source->numEdgeData;
335  int numTessFaces = 0;
336  int numLoops = source->numLoopData;
337  int numPolys = source->numPolyData;
338 
339  /* NOTE: Don't copy tessellation faces if not requested explicitly. */
340 
341  /* ensure these are created if they are made on demand */
342  source->getVertDataArray(source, CD_ORIGINDEX);
343  source->getEdgeDataArray(source, CD_ORIGINDEX);
344  source->getPolyDataArray(source, CD_ORIGINDEX);
345 
346  /* this initializes dm, and copies all non mvert/medge/mface layers */
347  DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys);
348  dm->deformedOnly = source->deformedOnly;
349  dm->cd_flag = source->cd_flag;
350  dm->dirty = source->dirty;
351 
352  /* Tessellation data is never copied, so tag it here.
353  * Only tag dirty layers if we really ignored tessellation faces.
354  */
356 
357  CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
358  CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
359 
360  /* now add mvert/medge/mface layers */
361  cddm->mvert = source->dupVertArray(source);
362  cddm->medge = source->dupEdgeArray(source);
363 
364  CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
365  CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
366 
367  DM_DupPolys(source, dm);
368 
371 
372  return dm;
373 }
void * DM_get_edge_data_layer(struct DerivedMesh *dm, int type)
Definition: DerivedMesh.cc:626
void * DM_get_edge_data(struct DerivedMesh *dm, int index, int type)
Definition: DerivedMesh.cc:599
void * DM_get_vert_data(struct DerivedMesh *dm, int index, int type)
Definition: DerivedMesh.cc:593
void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys)
Definition: DerivedMesh.cc:342
void * DM_get_tessface_data_layer(struct DerivedMesh *dm, int type)
Definition: DerivedMesh.cc:635
bool DM_release(DerivedMesh *dm)
Definition: DerivedMesh.cc:424
void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys)
Definition: DerivedMesh.cc:404
void DM_ensure_looptri_data(DerivedMesh *dm)
Definition: DerivedMesh.cc:493
void * DM_get_tessface_data(struct DerivedMesh *dm, int index, int type)
Definition: DerivedMesh.cc:605
void * DM_get_vert_data_layer(struct DerivedMesh *dm, int type)
Definition: DerivedMesh.cc:617
void DM_DupPolys(DerivedMesh *source, DerivedMesh *target)
Definition: DerivedMesh.cc:449
@ DM_TYPE_CDDM
@ DM_DIRTY_TESS_CDLAYERS
@ DM_DIRTY_NORMALS
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.c:2620
bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, eCDAllocType alloctype, int totelem)
Definition: customdata.c:2098
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.c:1933
void BKE_mesh_recalc_looptri(const struct MLoop *mloop, const struct MPoly *mpoly, const struct MVert *mvert, int totloop, int totpoly, struct MLoopTri *mlooptri)
void BKE_mesh_vert_poly_map_create(MeshElemMap **r_map, int **r_mem, const struct MPoly *mpoly, const struct MLoop *mloop, int totvert, int totpoly, int totloop)
General operations, lookup, etc. for blender objects.
A BVH for high poly meshes.
#define BLI_assert(a)
Definition: BLI_assert.h:58
MINLINE void normal_short_to_float_v3(float r[3], const short n[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define CD_MASK_NORMAL
#define CD_MASK_ORIGINDEX
@ CD_ORIGINDEX
@ CD_MVERT
#define CD_MASK_MDISPS
Object is a sort of wrapper for general info.
@ OB_MESH
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 void cdDM_getVert(DerivedMesh *dm, int index, MVert *r_vert)
static DerivedMesh * cdDM_from_mesh_ex(Mesh *mesh, eCDAllocType alloctype, const CustomData_MeshMasks *mask)
static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
static int cdDM_getNumTessFaces(DerivedMesh *dm)
Definition: cdderivedmesh.c:84
static void cdDM_recalc_looptri(DerivedMesh *dm)
static int cdDM_getNumLoops(DerivedMesh *dm)
Definition: cdderivedmesh.c:96
static void cdDM_free_internal(CDDerivedMesh *cddm)
static CDDerivedMesh * cdDM_create(const char *desc)
static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *r_edge)
static void cdDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
static const MeshElemMap * cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
static void cdDM_copyVertArray(DerivedMesh *dm, MVert *r_vert)
static int cdDM_getNumVerts(DerivedMesh *dm)
Definition: cdderivedmesh.c:74
static int cdDM_getNumEdges(DerivedMesh *dm)
Definition: cdderivedmesh.c:79
DerivedMesh * CDDM_from_mesh(Mesh *mesh)
static void cdDM_copyPolyArray(DerivedMesh *dm, MPoly *r_poly)
static void cdDM_getTessFace(DerivedMesh *dm, int index, MFace *r_face)
static void cdDM_copyTessFaceArray(DerivedMesh *dm, MFace *r_face)
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)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
struct PBVH * pbvh
Definition: cdderivedmesh.c:65
DerivedMesh dm
Definition: cdderivedmesh.c:54
MeshElemMap * pmap
Definition: cdderivedmesh.c:69
struct DerivedMesh::@15 looptris
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)
void *(* getEdgeData)(DerivedMesh *dm, int index, int type)
void *(* getTessFaceDataArray)(DerivedMesh *dm, int type)
CustomData polyData
struct MVert *(* dupVertArray)(DerivedMesh *dm)
int(* getNumTessFaces)(DerivedMesh *dm)
struct MLoopTri * array_wip
void(* copyVertArray)(DerivedMesh *dm, struct MVert *r_vert)
void *(* getTessFaceData)(DerivedMesh *dm, int index, int type)
void *(* getVertData)(DerivedMesh *dm, int index, int type)
void *(* getPolyDataArray)(DerivedMesh *dm, int type)
void(* getVert)(DerivedMesh *dm, int index, struct MVert *r_vert)
void *(* getEdgeDataArray)(DerivedMesh *dm, int type)
CustomData edgeData
void(* copyTessFaceArray)(DerivedMesh *dm, struct MFace *r_face)
void(* getEdge)(DerivedMesh *dm, int index, struct MEdge *r_edge)
const struct MeshElemMap *(* getPolyMap)(struct Object *ob, DerivedMesh *dm)
CustomData loopData
void(* recalcLoopTri)(DerivedMesh *dm)
struct MLoopTri * array
void(* getTessFace)(DerivedMesh *dm, int index, struct MFace *r_face)
void(* release)(DerivedMesh *dm)
void(* getVertCo)(DerivedMesh *dm, int index, float r_co[3])
DMDirtyFlag dirty
int(* getNumLoops)(DerivedMesh *dm)
float co[3]
short no[3]
int64_t cd_dirty_vert
struct CustomData pdata ldata
int totedge
char cd_flag
int totvert
struct MLoop * mloop
Mesh_Runtime runtime
struct CustomData vdata edata fdata
int totpoly
int totloop
struct MPoly * mpoly
void * data
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)