Blender  V2.93
meshtools.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) 2004 by Blender Foundation
17  * All rights reserved.
18  */
19 
27 #include "MEM_guardedalloc.h"
28 
29 #include "DNA_key_types.h"
30 #include "DNA_material_types.h"
31 #include "DNA_mesh_types.h"
32 #include "DNA_meshdata_types.h"
33 #include "DNA_modifier_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_scene_types.h"
36 #include "DNA_screen_types.h"
37 #include "DNA_view3d_types.h"
38 #include "DNA_workspace_types.h"
39 
40 #include "BLI_blenlib.h"
41 #include "BLI_math.h"
42 
43 #include "BKE_context.h"
44 #include "BKE_deform.h"
45 #include "BKE_editmesh.h"
46 #include "BKE_key.h"
47 #include "BKE_layer.h"
48 #include "BKE_lib_id.h"
49 #include "BKE_main.h"
50 #include "BKE_material.h"
51 #include "BKE_mesh.h"
52 #include "BKE_mesh_iterators.h"
53 #include "BKE_mesh_runtime.h"
54 #include "BKE_multires.h"
55 #include "BKE_object.h"
56 #include "BKE_object_deform.h"
57 #include "BKE_object_facemap.h"
58 #include "BKE_report.h"
59 
60 #include "DEG_depsgraph.h"
61 #include "DEG_depsgraph_build.h"
62 #include "DEG_depsgraph_query.h"
63 
64 #include "DRW_select_buffer.h"
65 
66 #include "ED_mesh.h"
67 #include "ED_object.h"
68 #include "ED_view3d.h"
69 
70 #include "WM_api.h"
71 #include "WM_types.h"
72 
73 /* * ********************** no editmode!!! *********** */
74 
75 /*********************** JOIN ***************************/
76 
77 /* join selected meshes into the active mesh, context sensitive
78  * return 0 if no join is made (error) and 1 if the join is done */
79 
81  Main *bmain,
82  Scene *scene,
83  Object *ob_dst,
84  Object *ob_src,
85  const float imat[4][4],
86  MVert **mvert_pp,
87  MEdge **medge_pp,
88  MLoop **mloop_pp,
89  MPoly **mpoly_pp,
90  CustomData *vdata,
91  CustomData *edata,
92  CustomData *ldata,
93  CustomData *pdata,
94  int totvert,
95  int totedge,
96  int totloop,
97  int totpoly,
98  Key *key,
99  Key *nkey,
100  Material **matar,
101  int *matmap,
102  int totcol,
103  int *vertofs,
104  int *edgeofs,
105  int *loopofs,
106  int *polyofs)
107 {
108  int a, b;
109 
110  Mesh *me = ob_src->data;
111  MVert *mvert = *mvert_pp;
112  MEdge *medge = *medge_pp;
113  MLoop *mloop = *mloop_pp;
114  MPoly *mpoly = *mpoly_pp;
115 
116  if (me->totvert) {
117  /* merge customdata flag */
118  ((Mesh *)ob_dst->data)->cd_flag |= me->cd_flag;
119 
120  /* standard data */
121  CustomData_merge(&me->vdata, vdata, CD_MASK_MESH.vmask, CD_DEFAULT, totvert);
122  CustomData_copy_data_named(&me->vdata, vdata, 0, *vertofs, me->totvert);
123 
124  /* vertex groups */
125  MDeformVert *dvert = CustomData_get(vdata, *vertofs, CD_MDEFORMVERT);
126  MDeformVert *dvert_src = CustomData_get(&me->vdata, 0, CD_MDEFORMVERT);
127 
128  /* Remap to correct new vgroup indices, if needed. */
129  if (dvert_src) {
130  BLI_assert(dvert != NULL);
131 
132  /* Build src to merged mapping of vgroup indices. */
133  int *vgroup_index_map;
134  int vgroup_index_map_len;
135  vgroup_index_map = BKE_object_defgroup_index_map_create(
136  ob_src, ob_dst, &vgroup_index_map_len);
138  dvert, me->totvert, vgroup_index_map, vgroup_index_map_len);
139  if (vgroup_index_map != NULL) {
140  MEM_freeN(vgroup_index_map);
141  }
142  }
143 
144  /* if this is the object we're merging into, no need to do anything */
145  if (ob_src != ob_dst) {
146  float cmat[4][4];
147 
148  /* Watch this: switch matrix multiplication order really goes wrong. */
149  mul_m4_m4m4(cmat, imat, ob_src->obmat);
150 
151  /* transform vertex coordinates into new space */
152  for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, mvert++) {
153  mul_m4_v3(cmat, mvert->co);
154  }
155 
156  /* For each shapekey in destination mesh:
157  * - if there's a matching one, copy it across
158  * (will need to transform vertices into new space...).
159  * - otherwise, just copy own coordinates of mesh
160  * (no need to transform vertex coordinates into new space).
161  */
162  if (key) {
163  /* if this mesh has any shapekeys, check first, otherwise just copy coordinates */
164  LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
165  /* get pointer to where to write data for this mesh in shapekey's data array */
166  float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs;
167 
168  /* check if this mesh has such a shapekey */
169  KeyBlock *okb = me->key ? BKE_keyblock_find_name(me->key, kb->name) : NULL;
170  if (okb) {
171  /* copy this mesh's shapekey to the destination shapekey
172  * (need to transform first) */
173  float(*ocos)[3] = okb->data;
174  for (a = 0; a < me->totvert; a++, cos++, ocos++) {
175  copy_v3_v3(*cos, *ocos);
176  mul_m4_v3(cmat, *cos);
177  }
178  }
179  else {
180  /* copy this mesh's vertex coordinates to the destination shapekey */
181  for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
182  copy_v3_v3(*cos, mvert->co);
183  }
184  }
185  }
186  }
187  }
188  else {
189  /* for each shapekey in destination mesh:
190  * - if it was an 'original', copy the appropriate data from nkey
191  * - otherwise, copy across plain coordinates (no need to transform coordinates)
192  */
193  if (key) {
194  LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
195  /* get pointer to where to write data for this mesh in shapekey's data array */
196  float(*cos)[3] = ((float(*)[3])kb->data) + *vertofs;
197 
198  /* check if this was one of the original shapekeys */
199  KeyBlock *okb = nkey ? BKE_keyblock_find_name(nkey, kb->name) : NULL;
200  if (okb) {
201  /* copy this mesh's shapekey to the destination shapekey */
202  float(*ocos)[3] = okb->data;
203  for (a = 0; a < me->totvert; a++, cos++, ocos++) {
204  copy_v3_v3(*cos, *ocos);
205  }
206  }
207  else {
208  /* copy base-coordinates to the destination shapekey */
209  for (a = 0, mvert = *mvert_pp; a < me->totvert; a++, cos++, mvert++) {
210  copy_v3_v3(*cos, mvert->co);
211  }
212  }
213  }
214  }
215  }
216  }
217 
218  if (me->totedge) {
219  CustomData_merge(&me->edata, edata, CD_MASK_MESH.emask, CD_DEFAULT, totedge);
220  CustomData_copy_data_named(&me->edata, edata, 0, *edgeofs, me->totedge);
221 
222  for (a = 0; a < me->totedge; a++, medge++) {
223  medge->v1 += *vertofs;
224  medge->v2 += *vertofs;
225  }
226  }
227 
228  if (me->totloop) {
229  if (ob_src != ob_dst) {
231 
233 
234  if ((mmd = get_multires_modifier(scene, ob_src, true))) {
236  bmain, ob_src, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl);
237  }
238  }
239 
240  CustomData_merge(&me->ldata, ldata, CD_MASK_MESH.lmask, CD_DEFAULT, totloop);
241  CustomData_copy_data_named(&me->ldata, ldata, 0, *loopofs, me->totloop);
242 
243  for (a = 0; a < me->totloop; a++, mloop++) {
244  mloop->v += *vertofs;
245  mloop->e += *edgeofs;
246  }
247  }
248 
249  if (me->totpoly) {
250  if (matmap) {
251  /* make mapping for materials */
252  for (a = 1; a <= ob_src->totcol; a++) {
253  Material *ma = BKE_object_material_get(ob_src, a);
254 
255  for (b = 0; b < totcol; b++) {
256  if (ma == matar[b]) {
257  matmap[a - 1] = b;
258  break;
259  }
260  }
261  }
262  }
263 
264  CustomData_merge(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_DEFAULT, totpoly);
265  CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly);
266 
267  for (a = 0; a < me->totpoly; a++, mpoly++) {
268  mpoly->loopstart += *loopofs;
269  mpoly->mat_nr = matmap ? matmap[mpoly->mat_nr] : 0;
270  }
271 
272  /* Face maps. */
273  int *fmap = CustomData_get(pdata, *polyofs, CD_FACEMAP);
274  int *fmap_src = CustomData_get(&me->pdata, 0, CD_FACEMAP);
275 
276  /* Remap to correct new face-map indices, if needed. */
277  if (fmap_src) {
278  BLI_assert(fmap != NULL);
279  int *fmap_index_map;
280  int fmap_index_map_len;
281  fmap_index_map = BKE_object_facemap_index_map_create(ob_src, ob_dst, &fmap_index_map_len);
282  BKE_object_facemap_index_map_apply(fmap, me->totpoly, fmap_index_map, fmap_index_map_len);
283  if (fmap_index_map != NULL) {
284  MEM_freeN(fmap_index_map);
285  }
286  }
287  }
288 
289  /* these are used for relinking (cannot be set earlier, or else reattaching goes wrong) */
290  *vertofs += me->totvert;
291  *mvert_pp += me->totvert;
292  *edgeofs += me->totedge;
293  *medge_pp += me->totedge;
294  *loopofs += me->totloop;
295  *mloop_pp += me->totloop;
296  *polyofs += me->totpoly;
297  *mpoly_pp += me->totpoly;
298 }
299 
300 /* Face Sets IDs are a sparse sequence, so this function offsets all the IDs by face_set_offset and
301  * updates face_set_offset with the maximum ID value. This way, when used in multiple meshes, all
302  * of them will have different IDs for their Face Sets. */
303 static void mesh_join_offset_face_sets_ID(const Mesh *mesh, int *face_set_offset)
304 {
305  if (!mesh->totpoly) {
306  return;
307  }
308 
309  int *face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
310  if (!face_sets) {
311  return;
312  }
313 
314  int max_face_set = 0;
315  for (int f = 0; f < mesh->totpoly; f++) {
316  /* As face sets encode the visibility in the integer sign, the offset needs to be added or
317  * subtracted depending on the initial sign of the integer to get the new ID. */
318  if (abs(face_sets[f]) <= *face_set_offset) {
319  if (face_sets[f] > 0) {
320  face_sets[f] += *face_set_offset;
321  }
322  else {
323  face_sets[f] -= *face_set_offset;
324  }
325  }
326  max_face_set = max_ii(max_face_set, abs(face_sets[f]));
327  }
328  *face_set_offset = max_face_set;
329 }
330 
332 {
333  Main *bmain = CTX_data_main(C);
336  Material **matar = NULL, *ma;
337  Mesh *me;
338  MVert *mvert = NULL;
339  MEdge *medge = NULL;
340  MPoly *mpoly = NULL;
341  MLoop *mloop = NULL;
342  Key *key, *nkey = NULL;
343  KeyBlock *kb, *kbn;
344  float imat[4][4];
345  int a, b, totcol, totmat = 0, totedge = 0, totvert = 0;
346  int totloop = 0, totpoly = 0, vertofs, *matmap = NULL;
347  int i, haskey = 0, edgeofs, loopofs, polyofs;
348  bool ok = false, join_parent = false;
349  bDeformGroup *dg, *odg;
350  CustomData vdata, edata, fdata, ldata, pdata;
351 
352  if (ob->mode & OB_MODE_EDIT) {
353  BKE_report(op->reports, RPT_WARNING, "Cannot join while in edit mode");
354  return OPERATOR_CANCELLED;
355  }
356 
357  /* ob is the object we are adding geometry to */
358  if (!ob || ob->type != OB_MESH) {
359  BKE_report(op->reports, RPT_WARNING, "Active object is not a mesh");
360  return OPERATOR_CANCELLED;
361  }
362 
364 
365  /* count & check */
366  CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
367  if (ob_iter->type == OB_MESH) {
368  me = ob_iter->data;
369 
370  totvert += me->totvert;
371  totedge += me->totedge;
372  totloop += me->totloop;
373  totpoly += me->totpoly;
374  totmat += ob_iter->totcol;
375 
376  if (ob_iter == ob) {
377  ok = true;
378  }
379 
380  if ((ob->parent != NULL) && (ob_iter == ob->parent)) {
381  join_parent = true;
382  }
383 
384  /* check for shapekeys */
385  if (me->key) {
386  haskey++;
387  }
388  }
389  }
390  CTX_DATA_END;
391 
392  /* Apply parent transform if the active object's parent was joined to it.
393  * Note: This doesn't apply recursive parenting. */
394  if (join_parent) {
395  ob->parent = NULL;
396  BKE_object_apply_mat4_ex(ob, ob->obmat, ob->parent, ob->parentinv, false);
397  }
398 
399  /* that way the active object is always selected */
400  if (ok == false) {
401  BKE_report(op->reports, RPT_WARNING, "Active object is not a selected mesh");
402  return OPERATOR_CANCELLED;
403  }
404 
405  /* Only join meshes if there are verts to join,
406  * there aren't too many, and we only had one mesh selected. */
407  me = (Mesh *)ob->data;
408  key = me->key;
409 
410  if (ELEM(totvert, 0, me->totvert)) {
411  BKE_report(op->reports, RPT_WARNING, "No mesh data to join");
412  return OPERATOR_CANCELLED;
413  }
414 
415  if (totvert > MESH_MAX_VERTS) {
416  BKE_reportf(op->reports,
417  RPT_WARNING,
418  "Joining results in %d vertices, limit is %ld",
419  totvert,
421  return OPERATOR_CANCELLED;
422  }
423 
424  /* remove tessface to ensure we don't hold references to invalid faces */
426 
427  /* new material indices and material array */
428  if (totmat) {
429  matar = MEM_callocN(sizeof(*matar) * totmat, "join_mesh matar");
430  matmap = MEM_callocN(sizeof(*matmap) * totmat, "join_mesh matmap");
431  }
432  totcol = ob->totcol;
433 
434  /* obact materials in new main array, is nicer start! */
435  for (a = 0; a < ob->totcol; a++) {
436  matar[a] = BKE_object_material_get(ob, a + 1);
437  id_us_plus((ID *)matar[a]);
438  /* increase id->us : will be lowered later */
439  }
440 
441  /* - if destination mesh had shapekeys, move them somewhere safe, and set up placeholders
442  * with arrays that are large enough to hold shapekey data for all meshes
443  * - if destination mesh didn't have shapekeys, but we encountered some in the meshes we're
444  * joining, set up a new keyblock and assign to the mesh
445  */
446  if (key) {
447  /* make a duplicate copy that will only be used here... (must remember to free it!) */
448  nkey = (Key *)BKE_id_copy(bmain, &key->id);
449 
450  /* for all keys in old block, clear data-arrays */
451  for (kb = key->block.first; kb; kb = kb->next) {
452  if (kb->data) {
453  MEM_freeN(kb->data);
454  }
455  kb->data = MEM_callocN(sizeof(float[3]) * totvert, "join_shapekey");
456  kb->totelem = totvert;
457  }
458  }
459  else if (haskey) {
460  /* add a new key-block and add to the mesh */
461  key = me->key = BKE_key_add(bmain, (ID *)me);
462  key->type = KEY_RELATIVE;
463  }
464 
465  /* Update face_set_id_offset with the face set data in the active object first. This way the Face
466  * Sets IDs in the active object are not the ones that are modified. */
467  Mesh *mesh_active = BKE_mesh_from_object(ob);
468  int face_set_id_offset = 0;
469  mesh_join_offset_face_sets_ID(mesh_active, &face_set_id_offset);
470 
471  /* Copy materials, vertex-groups, face sets & face-maps across objects. */
472  CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
473  /* only act if a mesh, and not the one we're joining to */
474  if ((ob != ob_iter) && (ob_iter->type == OB_MESH)) {
475  me = ob_iter->data;
476 
477  /* Join this object's vertex groups to the base one's */
478  for (dg = ob_iter->defbase.first; dg; dg = dg->next) {
479  /* See if this group exists in the object (if it doesn't, add it to the end) */
480  if (!BKE_object_defgroup_find_name(ob, dg->name)) {
481  odg = MEM_mallocN(sizeof(bDeformGroup), "join deformGroup");
482  memcpy(odg, dg, sizeof(bDeformGroup));
483  BLI_addtail(&ob->defbase, odg);
484  }
485  }
486  if (ob->defbase.first && ob->actdef == 0) {
487  ob->actdef = 1;
488  }
489 
490  /* Join this object's face maps to the base one's. */
491  LISTBASE_FOREACH (bFaceMap *, fmap, &ob_iter->fmaps) {
492  /* See if this group exists in the object (if it doesn't, add it to the end) */
493  if (BKE_object_facemap_find_name(ob, fmap->name) == NULL) {
494  bFaceMap *fmap_new = MEM_mallocN(sizeof(bFaceMap), "join faceMap");
495  memcpy(fmap_new, fmap, sizeof(bFaceMap));
496  BLI_addtail(&ob->fmaps, fmap_new);
497  }
498  }
499  if (ob->fmaps.first && ob->actfmap == 0) {
500  ob->actfmap = 1;
501  }
502 
503  mesh_join_offset_face_sets_ID(me, &face_set_id_offset);
504 
505  if (me->totvert) {
506  /* Add this object's materials to the base one's if they don't exist already
507  * (but only if limits not exceeded yet) */
508  if (totcol < MAXMAT) {
509  for (a = 1; a <= ob_iter->totcol; a++) {
510  ma = BKE_object_material_get(ob_iter, a);
511 
512  for (b = 0; b < totcol; b++) {
513  if (ma == matar[b]) {
514  break;
515  }
516  }
517  if (b == totcol) {
518  matar[b] = ma;
519  if (ma) {
520  id_us_plus(&ma->id);
521  }
522  totcol++;
523  }
524  if (totcol >= MAXMAT) {
525  break;
526  }
527  }
528  }
529 
530  /* if this mesh has shapekeys,
531  * check if destination mesh already has matching entries too */
532  if (me->key && key) {
533  /* for remapping KeyBlock.relative */
534  int *index_map = MEM_mallocN(sizeof(int) * me->key->totkey, __func__);
535  KeyBlock **kb_map = MEM_mallocN(sizeof(KeyBlock *) * me->key->totkey, __func__);
536 
537  for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) {
538  BLI_assert(i < me->key->totkey);
539 
540  kbn = BKE_keyblock_find_name(key, kb->name);
541  /* if key doesn't exist in destination mesh, add it */
542  if (kbn) {
543  index_map[i] = BLI_findindex(&key->block, kbn);
544  }
545  else {
546  index_map[i] = key->totkey;
547 
548  kbn = BKE_keyblock_add(key, kb->name);
549 
551 
552  /* adjust settings to fit (allocate a new data-array) */
553  kbn->data = MEM_callocN(sizeof(float[3]) * totvert, "joined_shapekey");
554  kbn->totelem = totvert;
555  }
556 
557  kb_map[i] = kbn;
558  }
559 
560  /* remap relative index values */
561  for (kb = me->key->block.first, i = 0; kb; kb = kb->next, i++) {
562  /* sanity check, should always be true */
563  if (LIKELY(kb->relative < me->key->totkey)) {
564  kb_map[i]->relative = index_map[kb->relative];
565  }
566  }
567 
568  MEM_freeN(index_map);
569  MEM_freeN(kb_map);
570  }
571  }
572  }
573  }
574  CTX_DATA_END;
575 
576  /* setup new data for destination mesh */
577  CustomData_reset(&vdata);
578  CustomData_reset(&edata);
579  CustomData_reset(&fdata);
580  CustomData_reset(&ldata);
581  CustomData_reset(&pdata);
582 
583  mvert = CustomData_add_layer(&vdata, CD_MVERT, CD_CALLOC, NULL, totvert);
584  medge = CustomData_add_layer(&edata, CD_MEDGE, CD_CALLOC, NULL, totedge);
585  mloop = CustomData_add_layer(&ldata, CD_MLOOP, CD_CALLOC, NULL, totloop);
586  mpoly = CustomData_add_layer(&pdata, CD_MPOLY, CD_CALLOC, NULL, totpoly);
587 
588  vertofs = 0;
589  edgeofs = 0;
590  loopofs = 0;
591  polyofs = 0;
592 
593  /* Inverse transform for all selected meshes in this object,
594  * See #object_join_exec for detailed comment on why the safe version is used. */
595  invert_m4_m4_safe_ortho(imat, ob->obmat);
596 
597  /* Add back active mesh first.
598  * This allows to keep things similar as they were, as much as possible
599  * (i.e. data from active mesh will remain first ones in new result of the merge,
600  * in same order for CD layers, etc). See also T50084.
601  */
603  bmain,
604  scene,
605  ob,
606  ob,
607  imat,
608  &mvert,
609  &medge,
610  &mloop,
611  &mpoly,
612  &vdata,
613  &edata,
614  &ldata,
615  &pdata,
616  totvert,
617  totedge,
618  totloop,
619  totpoly,
620  key,
621  nkey,
622  matar,
623  matmap,
624  totcol,
625  &vertofs,
626  &edgeofs,
627  &loopofs,
628  &polyofs);
629 
630  CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
631  if (ob_iter == ob) {
632  continue;
633  }
634  /* only join if this is a mesh */
635  if (ob_iter->type == OB_MESH) {
637  bmain,
638  scene,
639  ob,
640  ob_iter,
641  imat,
642  &mvert,
643  &medge,
644  &mloop,
645  &mpoly,
646  &vdata,
647  &edata,
648  &ldata,
649  &pdata,
650  totvert,
651  totedge,
652  totloop,
653  totpoly,
654  key,
655  nkey,
656  matar,
657  matmap,
658  totcol,
659  &vertofs,
660  &edgeofs,
661  &loopofs,
662  &polyofs);
663 
664  /* free base, now that data is merged */
665  if (ob_iter != ob) {
666  ED_object_base_free_and_unlink(bmain, scene, ob_iter);
667  }
668  }
669  }
670  CTX_DATA_END;
671 
672  /* return to mesh we're merging to */
673  me = ob->data;
674 
675  CustomData_free(&me->vdata, me->totvert);
676  CustomData_free(&me->edata, me->totedge);
677  CustomData_free(&me->ldata, me->totloop);
678  CustomData_free(&me->pdata, me->totpoly);
679 
680  me->totvert = totvert;
681  me->totedge = totedge;
682  me->totloop = totloop;
683  me->totpoly = totpoly;
684 
685  me->vdata = vdata;
686  me->edata = edata;
687  me->ldata = ldata;
688  me->pdata = pdata;
689 
690  /* tessface data removed above, no need to update */
692 
693  /* update normals in case objects with non-uniform scale are joined */
695 
696  /* old material array */
697  for (a = 1; a <= ob->totcol; a++) {
698  ma = ob->mat[a - 1];
699  if (ma) {
700  id_us_min(&ma->id);
701  }
702  }
703  for (a = 1; a <= me->totcol; a++) {
704  ma = me->mat[a - 1];
705  if (ma) {
706  id_us_min(&ma->id);
707  }
708  }
709  MEM_SAFE_FREE(ob->mat);
710  MEM_SAFE_FREE(ob->matbits);
711  MEM_SAFE_FREE(me->mat);
712 
713  if (totcol) {
714  me->mat = matar;
715  ob->mat = MEM_callocN(sizeof(*ob->mat) * totcol, "join obmatar");
716  ob->matbits = MEM_callocN(sizeof(*ob->matbits) * totcol, "join obmatbits");
717  MEM_freeN(matmap);
718  }
719 
720  ob->totcol = me->totcol = totcol;
721 
722  /* other mesh users */
723  BKE_objects_materials_test_all(bmain, (ID *)me);
724 
725  /* free temp copy of destination shapekeys (if applicable) */
726  if (nkey) {
727  /* We can assume nobody is using that ID currently. */
728  BKE_id_free_ex(bmain, nkey, LIB_ID_FREE_NO_UI_USER, false);
729  }
730 
731  /* ensure newly inserted keys are time sorted */
732  if (key && (key->type != KEY_RELATIVE)) {
733  BKE_key_sort(key);
734  }
735 
736  /* Due to dependency cycle some other object might access old derived data. */
738 
739  DEG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */
740 
742 
746 
747  return OPERATOR_FINISHED;
748 }
749 
750 /* -------------------------------------------------------------------- */
754 /* Append selected meshes vertex locations as shapes of the active mesh,
755  * return 0 if no join is made (error) and 1 of the join is done */
756 
758 {
759  Main *bmain = CTX_data_main(C);
761  Object *ob_active = CTX_data_active_object(C);
763  Mesh *me = (Mesh *)ob_active->data;
764  Mesh *selme = NULL;
765  Mesh *me_deformed = NULL;
766  Key *key = me->key;
767  KeyBlock *kb;
768  bool ok = false, nonequal_verts = false;
769 
770  CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
771  if (ob_iter == ob_active) {
772  continue;
773  }
774 
775  if (ob_iter->type == OB_MESH) {
776  selme = (Mesh *)ob_iter->data;
777 
778  if (selme->totvert == me->totvert) {
779  ok = true;
780  }
781  else {
782  nonequal_verts = 1;
783  }
784  }
785  }
786  CTX_DATA_END;
787 
788  if (!ok) {
789  if (nonequal_verts) {
790  BKE_report(op->reports, RPT_WARNING, "Selected meshes must have equal numbers of vertices");
791  }
792  else {
793  BKE_report(op->reports,
794  RPT_WARNING,
795  "No additional selected meshes with equal vertex count to join");
796  }
797  return OPERATOR_CANCELLED;
798  }
799 
800  if (key == NULL) {
801  key = me->key = BKE_key_add(bmain, (ID *)me);
802  key->type = KEY_RELATIVE;
803 
804  /* first key added, so it was the basis. initialize it with the existing mesh */
805  kb = BKE_keyblock_add(key, NULL);
806  BKE_keyblock_convert_from_mesh(me, key, kb);
807  }
808 
809  /* now ready to add new keys from selected meshes */
810  CTX_DATA_BEGIN (C, Object *, ob_iter, selected_editable_objects) {
811  if (ob_iter == ob_active) {
812  continue;
813  }
814 
815  if (ob_iter->type == OB_MESH) {
816  selme = (Mesh *)ob_iter->data;
817 
818  if (selme->totvert == me->totvert) {
819  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
820  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
821 
822  me_deformed = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
823 
824  if (!me_deformed) {
825  continue;
826  }
827 
828  kb = BKE_keyblock_add(key, ob_iter->id.name + 2);
829 
830  BKE_mesh_runtime_eval_to_meshkey(me_deformed, me, kb);
831  }
832  }
833  }
834  CTX_DATA_END;
835 
838 
839  return OPERATOR_FINISHED;
840 }
841 
844 /* -------------------------------------------------------------------- */
848 static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
849 
851  Mesh *me_eval,
852  Mesh **r_me_mirror,
853  BMEditMesh **r_em_mirror)
854 {
855  Mesh *me_mirror = NULL;
856  BMEditMesh *em_mirror = NULL;
857 
858  Mesh *me = ob->data;
859  if (me_eval != NULL) {
860  me_mirror = me_eval;
861  }
862  else if (me->edit_mesh != NULL) {
863  em_mirror = me->edit_mesh;
864  }
865  else {
866  me_mirror = me;
867  }
868 
869  *r_me_mirror = me_mirror;
870  *r_em_mirror = em_mirror;
871 }
872 
880 {
881  Mesh *me_mirror;
882  BMEditMesh *em_mirror;
883  mesh_mirror_topo_table_get_meshes(ob, me_eval, &me_mirror, &em_mirror);
884 
885  ED_mesh_mirrtopo_init(em_mirror, me_mirror, &mesh_topo_store, false);
886 }
887 
889 {
890  /* TODO: store this in object/object-data (keep unused argument for now). */
892 }
893 
894 /* Returns true on success. */
895 static bool ed_mesh_mirror_topo_table_update(Object *ob, Mesh *me_eval)
896 {
897  Mesh *me_mirror;
898  BMEditMesh *em_mirror;
899  mesh_mirror_topo_table_get_meshes(ob, me_eval, &me_mirror, &em_mirror);
900 
901  if (ED_mesh_mirrtopo_recalc_check(em_mirror, me_mirror, &mesh_topo_store)) {
902  ED_mesh_mirror_topo_table_begin(ob, me_eval);
903  }
904  return true;
905 }
906 
909 static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *me_eval, int index)
910 {
911  Mesh *me = ob->data;
912  MVert *mvert = me_eval ? me_eval->mvert : me->mvert;
913  float vec[3];
914 
915  mvert = &mvert[index];
916  vec[0] = -mvert->co[0];
917  vec[1] = mvert->co[1];
918  vec[2] = mvert->co[2];
919 
920  return ED_mesh_mirror_spatial_table_lookup(ob, NULL, me_eval, vec);
921 }
922 
923 static int mesh_get_x_mirror_vert_topo(Object *ob, Mesh *mesh, int index)
924 {
926  return -1;
927  }
928 
929  return mesh_topo_store.index_lookup[index];
930 }
931 
932 int mesh_get_x_mirror_vert(Object *ob, Mesh *me_eval, int index, const bool use_topology)
933 {
934  if (use_topology) {
935  return mesh_get_x_mirror_vert_topo(ob, me_eval, index);
936  }
937  return mesh_get_x_mirror_vert_spatial(ob, me_eval, index);
938 }
939 
940 static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, const float co[3])
941 {
942  float vec[3];
943  int i;
944 
945  /* ignore nan verts */
946  if ((isfinite(co[0]) == false) || (isfinite(co[1]) == false) || (isfinite(co[2]) == false)) {
947  return NULL;
948  }
949 
950  vec[0] = -co[0];
951  vec[1] = co[1];
952  vec[2] = co[2];
953 
954  i = ED_mesh_mirror_spatial_table_lookup(ob, em, NULL, vec);
955  if (i != -1) {
956  return BM_vert_at_index(em->bm, i);
957  }
958  return NULL;
959 }
960 
962  struct BMEditMesh *em,
963  BMVert *eve,
964  int index)
965 {
966  intptr_t poinval;
968  return NULL;
969  }
970 
971  if (index == -1) {
972  BMIter iter;
973  BMVert *v;
974 
975  index = 0;
976  BM_ITER_MESH (v, &iter, em->bm, BM_VERTS_OF_MESH) {
977  if (v == eve) {
978  break;
979  }
980  index++;
981  }
982 
983  if (index == em->bm->totvert) {
984  return NULL;
985  }
986  }
987 
988  poinval = mesh_topo_store.index_lookup[index];
989 
990  if (poinval != -1) {
991  return (BMVert *)(poinval);
992  }
993  return NULL;
994 }
995 
997  struct BMEditMesh *em,
998  BMVert *eve,
999  const float co[3],
1000  int index,
1001  const bool use_topology)
1002 {
1003  if (use_topology) {
1004  return editbmesh_get_x_mirror_vert_topo(ob, em, eve, index);
1005  }
1006  return editbmesh_get_x_mirror_vert_spatial(ob, em, co);
1007 }
1008 
1014 int ED_mesh_mirror_get_vert(Object *ob, int index)
1015 {
1016  Mesh *me = ob->data;
1017  BMEditMesh *em = me->edit_mesh;
1018  bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
1019  int index_mirr;
1020 
1021  if (em) {
1022  BMVert *eve, *eve_mirr;
1023  eve = BM_vert_at_index(em->bm, index);
1024  eve_mirr = editbmesh_get_x_mirror_vert(ob, em, eve, eve->co, index, use_topology);
1025  index_mirr = eve_mirr ? BM_elem_index_get(eve_mirr) : -1;
1026  }
1027  else {
1028  index_mirr = mesh_get_x_mirror_vert(ob, NULL, index, use_topology);
1029  }
1030 
1031  return index_mirr;
1032 }
1033 
1034 #if 0
1035 
1036 static float *editmesh_get_mirror_uv(
1037  BMEditMesh *em, int axis, float *uv, float *mirrCent, float *face_cent)
1038 {
1039  float vec[2];
1040  float cent_vec[2];
1041  float cent[2];
1042 
1043  /* ignore nan verts */
1044  if (isnan(uv[0]) || !isfinite(uv[0]) || isnan(uv[1]) || !isfinite(uv[1])) {
1045  return NULL;
1046  }
1047 
1048  if (axis) {
1049  vec[0] = uv[0];
1050  vec[1] = -((uv[1]) - mirrCent[1]) + mirrCent[1];
1051 
1052  cent_vec[0] = face_cent[0];
1053  cent_vec[1] = -((face_cent[1]) - mirrCent[1]) + mirrCent[1];
1054  }
1055  else {
1056  vec[0] = -((uv[0]) - mirrCent[0]) + mirrCent[0];
1057  vec[1] = uv[1];
1058 
1059  cent_vec[0] = -((face_cent[0]) - mirrCent[0]) + mirrCent[0];
1060  cent_vec[1] = face_cent[1];
1061  }
1062 
1063  /* TODO - Optimize */
1064  {
1065  BMIter iter;
1066  BMFace *efa;
1067 
1068  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
1069  BM_face_uv_calc_center_median(efa, cd_loop_uv_offset, cent);
1070 
1071  if ((fabsf(cent[0] - cent_vec[0]) < 0.001f) && (fabsf(cent[1] - cent_vec[1]) < 0.001f)) {
1072  BMIter liter;
1073  BMLoop *l;
1074 
1075  BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
1077  if ((fabsf(luv->uv[0] - vec[0]) < 0.001f) && (fabsf(luv->uv[1] - vec[1]) < 0.001f)) {
1078  return luv->uv;
1079  }
1080  }
1081  }
1082  }
1083  }
1084 
1085  return NULL;
1086 }
1087 
1088 #endif
1089 
1090 static uint mirror_facehash(const void *ptr)
1091 {
1092  const MFace *mf = ptr;
1093  uint v0, v1;
1094 
1095  if (mf->v4) {
1096  v0 = MIN4(mf->v1, mf->v2, mf->v3, mf->v4);
1097  v1 = MAX4(mf->v1, mf->v2, mf->v3, mf->v4);
1098  }
1099  else {
1100  v0 = MIN3(mf->v1, mf->v2, mf->v3);
1101  v1 = MAX3(mf->v1, mf->v2, mf->v3);
1102  }
1103 
1104  return ((v0 * 39) ^ (v1 * 31));
1105 }
1106 
1108 {
1109  if (b->v4) {
1110  if (a->v1 == b->v1 && a->v2 == b->v2 && a->v3 == b->v3 && a->v4 == b->v4) {
1111  return 0;
1112  }
1113  if (a->v4 == b->v1 && a->v1 == b->v2 && a->v2 == b->v3 && a->v3 == b->v4) {
1114  return 1;
1115  }
1116  if (a->v3 == b->v1 && a->v4 == b->v2 && a->v1 == b->v3 && a->v2 == b->v4) {
1117  return 2;
1118  }
1119  if (a->v2 == b->v1 && a->v3 == b->v2 && a->v4 == b->v3 && a->v1 == b->v4) {
1120  return 3;
1121  }
1122  }
1123  else {
1124  if (a->v1 == b->v1 && a->v2 == b->v2 && a->v3 == b->v3) {
1125  return 0;
1126  }
1127  if (a->v3 == b->v1 && a->v1 == b->v2 && a->v2 == b->v3) {
1128  return 1;
1129  }
1130  if (a->v2 == b->v1 && a->v3 == b->v2 && a->v1 == b->v3) {
1131  return 2;
1132  }
1133  }
1134 
1135  return -1;
1136 }
1137 
1138 static bool mirror_facecmp(const void *a, const void *b)
1139 {
1140  return (mirror_facerotation((MFace *)a, (MFace *)b) == -1);
1141 }
1142 
1143 /* This is a Mesh-based copy of mesh_get_x_mirror_faces() */
1145 {
1146  Mesh *me = ob->data;
1147  MVert *mv, *mvert;
1148  MFace mirrormf, *mf, *hashmf, *mface;
1149  GHash *fhash;
1150  int *mirrorverts, *mirrorfaces;
1151 
1152  BLI_assert(em == NULL); /* Does not work otherwise, currently... */
1153 
1154  const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
1155  const int totvert = me_eval ? me_eval->totvert : me->totvert;
1156  const int totface = me_eval ? me_eval->totface : me->totface;
1157  int a;
1158 
1159  mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts");
1160  mirrorfaces = MEM_callocN(sizeof(int[2]) * totface, "MirrorFaces");
1161 
1162  mvert = me_eval ? me_eval->mvert : me->mvert;
1163  mface = me_eval ? me_eval->mface : me->mface;
1164 
1165  ED_mesh_mirror_spatial_table_begin(ob, em, me_eval);
1166 
1167  for (a = 0, mv = mvert; a < totvert; a++, mv++) {
1168  mirrorverts[a] = mesh_get_x_mirror_vert(ob, me_eval, a, use_topology);
1169  }
1170 
1172 
1173  fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface);
1174  for (a = 0, mf = mface; a < totface; a++, mf++) {
1175  BLI_ghash_insert(fhash, mf, mf);
1176  }
1177 
1178  for (a = 0, mf = mface; a < totface; a++, mf++) {
1179  mirrormf.v1 = mirrorverts[mf->v3];
1180  mirrormf.v2 = mirrorverts[mf->v2];
1181  mirrormf.v3 = mirrorverts[mf->v1];
1182  mirrormf.v4 = (mf->v4) ? mirrorverts[mf->v4] : 0;
1183 
1184  /* make sure v4 is not 0 if a quad */
1185  if (mf->v4 && mirrormf.v4 == 0) {
1186  SWAP(uint, mirrormf.v1, mirrormf.v3);
1187  SWAP(uint, mirrormf.v2, mirrormf.v4);
1188  }
1189 
1190  hashmf = BLI_ghash_lookup(fhash, &mirrormf);
1191  if (hashmf) {
1192  mirrorfaces[a * 2] = hashmf - mface;
1193  mirrorfaces[a * 2 + 1] = mirror_facerotation(&mirrormf, hashmf);
1194  }
1195  else {
1196  mirrorfaces[a * 2] = -1;
1197  }
1198  }
1199 
1200  BLI_ghash_free(fhash, NULL, NULL);
1201  MEM_freeN(mirrorverts);
1202 
1203  return mirrorfaces;
1204 }
1205 
1206 /* selection, vertex and face */
1207 /* returns 0 if not found, otherwise 1 */
1208 
1215 bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
1216 {
1217  ViewContext vc;
1218  Mesh *me = ob->data;
1219 
1220  BLI_assert(me && GS(me->id.name) == ID_ME);
1221 
1222  if (!me || me->totpoly == 0) {
1223  return false;
1224  }
1225 
1229 
1230  if (dist_px) {
1231  /* sample rect to increase chances of selecting, so that when clicking
1232  * on an edge in the backbuf, we can still select a face */
1234  vc.depsgraph, vc.region, vc.v3d, mval, 1, me->totpoly + 1, &dist_px);
1235  }
1236  else {
1237  /* sample only on the exact position */
1238  *r_index = DRW_select_buffer_sample_point(vc.depsgraph, vc.region, vc.v3d, mval);
1239  }
1240 
1241  if ((*r_index) == 0 || (*r_index) > (uint)me->totpoly) {
1242  return false;
1243  }
1244 
1245  (*r_index)--;
1246 
1247  return true;
1248 }
1249 
1251  /* context */
1252  struct ARegion *region,
1253  const float mval[2],
1254  /* mesh data (evaluated) */
1255  const MPoly *mp,
1256  const MVert *mvert,
1257  const MLoop *mloop,
1258  /* return values */
1259  float *r_len_best,
1260  int *r_v_idx_best)
1261 {
1262  const MLoop *ml;
1263  int j = mp->totloop;
1264  for (ml = &mloop[mp->loopstart]; j--; ml++) {
1265  float sco[2];
1266  const int v_idx = ml->v;
1267  const float *co = mvert[v_idx].co;
1269  const float len_test = len_manhattan_v2v2(mval, sco);
1270  if (len_test < *r_len_best) {
1271  *r_len_best = len_test;
1272  *r_v_idx_best = v_idx;
1273  }
1274  }
1275  }
1276 }
1282  bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
1283 {
1285  uint poly_index;
1286  Mesh *me = ob->data;
1287 
1288  BLI_assert(me && GS(me->id.name) == ID_ME);
1289 
1290  if (ED_mesh_pick_face(C, ob, mval, dist_px, &poly_index)) {
1291  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
1292  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
1293  struct ARegion *region = CTX_wm_region(C);
1294 
1295  /* derived mesh to find deformed locations */
1296  Mesh *me_eval = mesh_get_eval_final(
1297  depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH_ORIGINDEX);
1298 
1299  int v_idx_best = ORIGINDEX_NONE;
1300 
1301  /* find the vert closest to 'mval' */
1302  const float mval_f[2] = {UNPACK2(mval)};
1303  float len_best = FLT_MAX;
1304 
1305  MPoly *me_eval_mpoly;
1306  MLoop *me_eval_mloop;
1307  MVert *me_eval_mvert;
1308  uint me_eval_mpoly_len;
1309  const int *index_mp_to_orig;
1310 
1311  me_eval_mpoly = me_eval->mpoly;
1312  me_eval_mloop = me_eval->mloop;
1313  me_eval_mvert = me_eval->mvert;
1314 
1315  me_eval_mpoly_len = me_eval->totpoly;
1316 
1317  index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
1318 
1319  /* tag all verts using this face */
1320  if (index_mp_to_orig) {
1321  uint i;
1322 
1323  for (i = 0; i < me_eval_mpoly_len; i++) {
1324  if (index_mp_to_orig[i] == poly_index) {
1326  mval_f,
1327  &me_eval_mpoly[i],
1328  me_eval_mvert,
1329  me_eval_mloop,
1330  &len_best,
1331  &v_idx_best);
1332  }
1333  }
1334  }
1335  else {
1336  if (poly_index < me_eval_mpoly_len) {
1338  mval_f,
1339  &me_eval_mpoly[poly_index],
1340  me_eval_mvert,
1341  me_eval_mloop,
1342  &len_best,
1343  &v_idx_best);
1344  }
1345  }
1346 
1347  /* map 'dm -> me' r_index if possible */
1348  if (v_idx_best != ORIGINDEX_NONE) {
1349  const int *index_mv_to_orig;
1350  index_mv_to_orig = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
1351  if (index_mv_to_orig) {
1352  v_idx_best = index_mv_to_orig[v_idx_best];
1353  }
1354  }
1355 
1356  if ((v_idx_best != ORIGINDEX_NONE) && (v_idx_best < me->totvert)) {
1357  *r_index = v_idx_best;
1358  return true;
1359  }
1360  }
1361 
1362  return false;
1363 }
1364 
1371 typedef struct VertPickData {
1372  const MVert *mvert;
1373  const float *mval_f; /* [2] */
1375 
1376  /* runtime */
1377  float len_best;
1380 
1381 static void ed_mesh_pick_vert__mapFunc(void *userData,
1382  int index,
1383  const float co[3],
1384  const float UNUSED(no_f[3]),
1385  const short UNUSED(no_s[3]))
1386 {
1387  VertPickData *data = userData;
1388  if ((data->mvert[index].flag & ME_HIDE) == 0) {
1389  float sco[2];
1390 
1392  V3D_PROJ_RET_OK) {
1393  const float len = len_manhattan_v2v2(data->mval_f, sco);
1394  if (len < data->len_best) {
1395  data->len_best = len;
1396  data->v_idx_best = index;
1397  }
1398  }
1399  }
1400 }
1402  bContext *C, Object *ob, const int mval[2], uint dist_px, bool use_zbuf, uint *r_index)
1403 {
1404  ViewContext vc;
1405  Mesh *me = ob->data;
1406 
1407  BLI_assert(me && GS(me->id.name) == ID_ME);
1408 
1409  if (!me || me->totvert == 0) {
1410  return false;
1411  }
1412 
1416 
1417  if (use_zbuf) {
1418  if (dist_px > 0) {
1419  /* sample rect to increase chances of selecting, so that when clicking
1420  * on an face in the backbuf, we can still select a vert */
1422  vc.depsgraph, vc.region, vc.v3d, mval, 1, me->totvert + 1, &dist_px);
1423  }
1424  else {
1425  /* sample only on the exact position */
1426  *r_index = DRW_select_buffer_sample_point(vc.depsgraph, vc.region, vc.v3d, mval);
1427  }
1428 
1429  if ((*r_index) == 0 || (*r_index) > (uint)me->totvert) {
1430  return false;
1431  }
1432 
1433  (*r_index)--;
1434  }
1435  else {
1436  Scene *scene_eval = DEG_get_evaluated_scene(vc.depsgraph);
1437  Object *ob_eval = DEG_get_evaluated_object(vc.depsgraph, ob);
1438 
1439  /* derived mesh to find deformed locations */
1440  Mesh *me_eval = mesh_get_eval_final(vc.depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH);
1441  ARegion *region = vc.region;
1442  RegionView3D *rv3d = region->regiondata;
1443 
1444  /* find the vert closest to 'mval' */
1445  const float mval_f[2] = {(float)mval[0], (float)mval[1]};
1446 
1447  VertPickData data = {NULL};
1448 
1449  ED_view3d_init_mats_rv3d(ob, rv3d);
1450 
1451  if (me_eval == NULL) {
1452  return false;
1453  }
1454 
1455  /* setup data */
1456  data.mvert = me->mvert;
1457  data.region = region;
1458  data.mval_f = mval_f;
1459  data.len_best = FLT_MAX;
1460  data.v_idx_best = -1;
1461 
1463 
1464  if (data.v_idx_best == -1) {
1465  return false;
1466  }
1467 
1468  *r_index = data.v_idx_best;
1469  }
1470 
1471  return true;
1472 }
1473 
1475 {
1476  if (ob->mode & OB_MODE_EDIT && ob->type == OB_MESH && ob->defbase.first) {
1477  Mesh *me = ob->data;
1478  BMesh *bm = me->edit_mesh->bm;
1479  const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT);
1480 
1481  if (cd_dvert_offset != -1) {
1483 
1484  if (eve) {
1485  if (r_eve) {
1486  *r_eve = eve;
1487  }
1488  return BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
1489  }
1490  }
1491  }
1492 
1493  if (r_eve) {
1494  *r_eve = NULL;
1495  }
1496  return NULL;
1497 }
1498 
1500 {
1501  Mesh *me = ob->data;
1502  int index = BKE_mesh_mselect_active_get(me, ME_VSEL);
1503  if (r_index) {
1504  *r_index = index;
1505  }
1506  if (index == -1 || me->dvert == NULL) {
1507  return NULL;
1508  }
1509  return me->dvert + index;
1510 }
1511 
1513 {
1514  if (ob->type == OB_MESH) {
1515  if (ob->mode & OB_MODE_EDIT) {
1516  return ED_mesh_active_dvert_get_em(ob, NULL);
1517  }
1518  return ED_mesh_active_dvert_get_ob(ob, NULL);
1519  }
1520  return NULL;
1521 }
1522 
1523 void EDBM_mesh_stats_multi(struct Object **objects,
1524  const uint objects_len,
1525  int totelem[3],
1526  int totelem_sel[3])
1527 {
1528  if (totelem) {
1529  totelem[0] = 0;
1530  totelem[1] = 0;
1531  totelem[2] = 0;
1532  }
1533  if (totelem_sel) {
1534  totelem_sel[0] = 0;
1535  totelem_sel[1] = 0;
1536  totelem_sel[2] = 0;
1537  }
1538 
1539  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1540  Object *obedit = objects[ob_index];
1541  BMEditMesh *em = BKE_editmesh_from_object(obedit);
1542  BMesh *bm = em->bm;
1543  if (totelem) {
1544  totelem[0] += bm->totvert;
1545  totelem[1] += bm->totedge;
1546  totelem[2] += bm->totface;
1547  }
1548  if (totelem_sel) {
1549  totelem_sel[0] += bm->totvertsel;
1550  totelem_sel[1] += bm->totedgesel;
1551  totelem_sel[2] += bm->totfacesel;
1552  }
1553  }
1554 }
1555 
1556 void EDBM_mesh_elem_index_ensure_multi(Object **objects, const uint objects_len, const char htype)
1557 {
1558  int elem_offset[4] = {0, 0, 0, 0};
1559  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1560  Object *obedit = objects[ob_index];
1561  BMEditMesh *em = BKE_editmesh_from_object(obedit);
1562  BMesh *bm = em->bm;
1564  }
1565 }
typedef float(TangentPoint)[2]
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:252
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
#define CTX_DATA_END
Definition: BKE_context.h:260
void CustomData_copy_data_named(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
void CustomData_free(struct CustomData *data, int totelem)
Definition: customdata.c:2239
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX
Definition: customdata.c:1926
@ CD_CALLOC
@ CD_DEFAULT
const CustomData_MeshMasks CD_MASK_BAREMESH
Definition: customdata.c:1919
#define ORIGINDEX_NONE
void * CustomData_get_layer(const struct CustomData *data, int type)
void * CustomData_bmesh_get(const struct CustomData *data, void *block, 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_get(const struct CustomData *data, int index, int type)
int CustomData_get_offset(const struct CustomData *data, int type)
const CustomData_MeshMasks CD_MASK_MESH
Definition: customdata.c:1933
void CustomData_reset(struct CustomData *data)
Definition: customdata.c:2233
support for deformation groups and hooks.
struct bDeformGroup * BKE_object_defgroup_find_name(const struct Object *ob, const char *name)
BMEditMesh * BKE_editmesh_from_object(struct Object *ob)
Return the BMEditMesh for a given object.
Definition: editmesh.c:85
struct KeyBlock * BKE_keyblock_find_name(struct Key *key, const char name[])
Definition: key.c:1944
void BKE_keyblock_copy_settings(struct KeyBlock *kb_dst, const struct KeyBlock *kb_src)
void BKE_key_sort(struct Key *key)
Definition: key.c:316
void BKE_keyblock_convert_from_mesh(struct Mesh *me, struct Key *key, struct KeyBlock *kb)
Definition: key.c:2208
struct KeyBlock * BKE_keyblock_add(struct Key *key, const char *name)
Definition: key.c:1817
struct Key * BKE_key_add(struct Main *bmain, struct ID *id)
Definition: key.c:259
struct ID * BKE_id_copy(struct Main *bmain, const struct ID *id)
void id_us_min(struct ID *id)
Definition: lib_id.c:297
@ LIB_ID_FREE_NO_UI_USER
Definition: BKE_lib_id.h:204
void id_us_plus(struct ID *id)
Definition: lib_id.c:288
void BKE_id_free_ex(struct Main *bmain, void *idv, int flag, const bool use_flag_from_idtag)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
Definition: material.c:697
void BKE_objects_materials_test_all(struct Main *bmain, struct ID *id)
Definition: material.c:784
void BKE_mesh_tessface_clear(struct Mesh *mesh)
Definition: mesh.c:1567
struct Mesh * BKE_mesh_from_object(struct Object *ob)
Definition: mesh.c:1271
int BKE_mesh_mselect_active_get(struct Mesh *me, int type)
Definition: mesh.c:1693
void BKE_mesh_calc_normals(struct Mesh *me)
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd)
Definition: mesh.c:766
@ MESH_FOREACH_NOP
void BKE_mesh_foreach_mapped_vert(struct Mesh *mesh, void(*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]), void *userData, MeshForeachFlag flag)
struct Mesh * mesh_get_eval_deform(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
struct Mesh * mesh_get_eval_final(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
void BKE_mesh_runtime_eval_to_meshkey(struct Mesh *me_deformed, struct Mesh *me, struct KeyBlock *kb)
Definition: DerivedMesh.cc:524
void multiresModifier_prepare_join(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct Object *to_ob)
Definition: multires.c:1461
struct MultiresModifierData * get_multires_modifier(struct Scene *scene, struct Object *ob, bool use_first)
Definition: multires.c:336
General operations, lookup, etc. for blender objects.
void BKE_object_apply_mat4_ex(struct Object *ob, const float mat[4][4], struct Object *parent, const float parentinv[4][4], const bool use_compat)
Definition: object.c:3708
void BKE_object_free_derived_caches(struct Object *ob)
Definition: object.c:1719
Functions for dealing with objects and deform verts, used by painting and tools.
int * BKE_object_defgroup_index_map_create(struct Object *ob_src, struct Object *ob_dst, int *r_map_len)
void BKE_object_defgroup_index_map_apply(struct MDeformVert *dvert, int dvert_len, const int *map, int map_len)
Functions for dealing with object face-maps.
int * BKE_object_facemap_index_map_create(struct Object *ob_src, struct Object *ob_dst, int *r_map_len)
void BKE_object_facemap_index_map_apply(int *fmap, int fmap_len, const int *map, int map_len)
struct bFaceMap * BKE_object_facemap_find_name(struct Object *ob, const char *name)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_INLINE
GHash * BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:707
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE int max_ii(int a, int b)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
void invert_m4_m4_safe_ortho(float Ainv[4][4], const float A[4][4])
Definition: math_matrix.c:3287
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:83
#define MIN4(a, b, c, d)
#define UNPACK2(a)
#define MAX3(a, b, c)
#define MIN3(a, b, c)
#define SWAP(type, a, b)
#define UNUSED(x)
#define ELEM(...)
#define MAX4(a, b, c, d)
#define LIKELY(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
@ ID_RECALC_SELECT
Definition: DNA_ID.h:638
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ ID_ME
Definition: DNA_ID_enums.h:60
@ CD_FACEMAP
@ CD_MDEFORMVERT
@ CD_ORIGINDEX
@ CD_SCULPT_FACE_SETS
@ CD_MVERT
@ CD_MLOOPUV
@ KEY_RELATIVE
#define MAXMAT
#define MESH_MAX_VERTS
@ ME_EDIT_MIRROR_TOPO
@ ME_VSEL
@ ME_HIDE
@ OB_MODE_EDIT
Object is a sort of wrapper for general info.
@ OB_MESH
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
uint DRW_select_buffer_find_nearest_to_point(struct Depsgraph *depsgraph, struct ARegion *region, struct View3D *v3d, const int center[2], const uint id_min, const uint id_max, uint *dist)
uint DRW_select_buffer_sample_point(struct Depsgraph *depsgraph, struct ARegion *region, struct View3D *v3d, const int center[2])
bool ED_mesh_mirrtopo_recalc_check(struct BMEditMesh *em, struct Mesh *me, MirrTopoStore_t *mesh_topo_store)
void ED_mesh_mirrtopo_init(struct BMEditMesh *em, struct Mesh *me, MirrTopoStore_t *mesh_topo_store, const bool skip_em_vert_array_init)
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store)
void ED_mesh_mirror_spatial_table_begin(struct Object *ob, struct BMEditMesh *em, struct Mesh *me_eval)
void ED_mesh_mirror_spatial_table_end(struct Object *ob)
int ED_mesh_mirror_spatial_table_lookup(struct Object *ob, struct BMEditMesh *em, struct Mesh *me_eval, const float co[3])
bool ED_object_multires_update_totlevels_cb(struct Object *ob, void *totlevel_v)
bool ED_object_iter_other(struct Main *bmain, struct Object *orig_ob, const bool include_orig, bool(*callback)(struct Object *ob, void *callback_data), void *callback_data)
void ED_object_base_free_and_unlink(struct Main *bmain, struct Scene *scene, struct Object *ob)
Definition: object_add.c:1958
void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
Definition: space_view3d.c:190
@ V3D_PROJ_TEST_NOP
Definition: ED_view3d.h:193
eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *region, const float co[3], float r_co[2], const eV3DProjTest flag)
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc, struct Depsgraph *depsgraph)
@ V3D_PROJ_RET_OK
Definition: ED_view3d.h:176
void ED_view3d_select_id_validate(struct ViewContext *vc)
Definition: view3d_draw.c:2192
#define V3D_PROJ_TEST_CLIP_DEFAULT
Definition: ED_view3d.h:201
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition: RandGen.cpp:39
#define ND_OB_ACTIVE
Definition: WM_types.h:340
#define NC_SCENE
Definition: WM_types.h:279
#define ND_LAYER_CONTENT
Definition: WM_types.h:354
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:530
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#define BM_ITER_ELEM(ele, iter, data, itype)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_FACE
ATTR_WARN_UNUSED_RESULT BMesh * bm
BMVert * BM_mesh_active_vert_get(BMesh *bm)
void BM_mesh_elem_index_ensure_ex(BMesh *bm, const char htype, int elem_offset[4])
Definition: bmesh_mesh.c:2038
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
Definition: bmesh_mesh.h:98
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
void BM_face_uv_calc_center_median(const BMFace *f, const int cd_loop_uv_offset, float r_cent[2])
Scene scene
const Depsgraph * depsgraph
static int elem_offset(const SDNA *sdna, const char *type, const char *name, const SDNA_Struct *old)
Definition: dna_genfile.c:988
#define GS(x)
Definition: iris.c:241
#define fabsf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static bool mirror_facecmp(const void *a, const void *b)
Definition: meshtools.c:1138
void ED_mesh_mirror_topo_table_begin(Object *ob, Mesh *me_eval)
Definition: meshtools.c:879
static void ed_mesh_pick_face_vert__mpoly_find(struct ARegion *region, const float mval[2], const MPoly *mp, const MVert *mvert, const MLoop *mloop, float *r_len_best, int *r_v_idx_best)
Definition: meshtools.c:1250
static void ed_mesh_pick_vert__mapFunc(void *userData, int index, const float co[3], const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
Definition: meshtools.c:1381
int * mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, Mesh *me_eval)
Definition: meshtools.c:1144
static uint mirror_facehash(const void *ptr)
Definition: meshtools.c:1090
static bool ed_mesh_mirror_topo_table_update(Object *ob, Mesh *me_eval)
Definition: meshtools.c:895
static void join_mesh_single(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *ob_dst, Object *ob_src, const float imat[4][4], MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp, CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata, int totvert, int totedge, int totloop, int totpoly, Key *key, Key *nkey, Material **matar, int *matmap, int totcol, int *vertofs, int *edgeofs, int *loopofs, int *polyofs)
Definition: meshtools.c:80
int ED_mesh_shapes_join_objects_exec(bContext *C, wmOperator *op)
Definition: meshtools.c:757
int mesh_get_x_mirror_vert(Object *ob, Mesh *me_eval, int index, const bool use_topology)
Definition: meshtools.c:932
struct VertPickData VertPickData
static int mesh_get_x_mirror_vert_spatial(Object *ob, Mesh *me_eval, int index)
Definition: meshtools.c:909
int ED_mesh_mirror_get_vert(Object *ob, int index)
Definition: meshtools.c:1014
int ED_mesh_join_objects_exec(bContext *C, wmOperator *op)
Definition: meshtools.c:331
MDeformVert * ED_mesh_active_dvert_get_only(Object *ob)
Definition: meshtools.c:1512
bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
Definition: meshtools.c:1281
void EDBM_mesh_elem_index_ensure_multi(Object **objects, const uint objects_len, const char htype)
Definition: meshtools.c:1556
MDeformVert * ED_mesh_active_dvert_get_em(Object *ob, BMVert **r_eve)
Definition: meshtools.c:1474
static MirrTopoStore_t mesh_topo_store
Definition: meshtools.c:848
BMVert * editbmesh_get_x_mirror_vert(Object *ob, struct BMEditMesh *em, BMVert *eve, const float co[3], int index, const bool use_topology)
Definition: meshtools.c:996
bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], uint dist_px, uint *r_index)
Definition: meshtools.c:1215
static BMVert * editbmesh_get_x_mirror_vert_topo(Object *ob, struct BMEditMesh *em, BMVert *eve, int index)
Definition: meshtools.c:961
void ED_mesh_mirror_topo_table_end(Object *UNUSED(ob))
Definition: meshtools.c:888
static int mirror_facerotation(MFace *a, MFace *b)
Definition: meshtools.c:1107
BLI_INLINE void mesh_mirror_topo_table_get_meshes(Object *ob, Mesh *me_eval, Mesh **r_me_mirror, BMEditMesh **r_em_mirror)
Definition: meshtools.c:850
static BMVert * editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, const float co[3])
Definition: meshtools.c:940
MDeformVert * ED_mesh_active_dvert_get_ob(Object *ob, int *r_index)
Definition: meshtools.c:1499
bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], uint dist_px, bool use_zbuf, uint *r_index)
Definition: meshtools.c:1401
static void mesh_join_offset_face_sets_ID(const Mesh *mesh, int *face_set_offset)
Definition: meshtools.c:303
static int mesh_get_x_mirror_vert_topo(Object *ob, Mesh *mesh, int index)
Definition: meshtools.c:923
void EDBM_mesh_stats_multi(struct Object **objects, const uint objects_len, int totelem[3], int totelem_sel[3])
Definition: meshtools.c:1523
bool isfinite(uchar)
Definition: image.cpp:44
static unsigned a[3]
Definition: RandGen.cpp:92
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:319
bool isnan(double i)
Definition: numeric.h:451
_W64 int intptr_t
Definition: stdint.h:121
void * regiondata
struct BMesh * bm
Definition: BKE_editmesh.h:52
void * data
Definition: bmesh_class.h:63
BMHeader head
Definition: bmesh_class.h:157
float co[3]
Definition: bmesh_class.h:99
int totvert
Definition: bmesh_class.h:297
int totfacesel
Definition: bmesh_class.h:298
CustomData vdata
Definition: bmesh_class.h:337
int totedge
Definition: bmesh_class.h:297
int totvertsel
Definition: bmesh_class.h:298
int totedgesel
Definition: bmesh_class.h:298
CustomData ldata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
Definition: DNA_ID.h:273
char name[66]
Definition: DNA_ID.h:283
char name[64]
Definition: DNA_key_types.h:68
struct KeyBlock * next
Definition: DNA_key_types.h:41
short relative
Definition: DNA_key_types.h:57
void * data
Definition: DNA_key_types.h:66
int totkey
ID id
Definition: DNA_key_types.h:79
char type
ListBase block
void * first
Definition: DNA_listBase.h:47
unsigned int v1
unsigned int v2
unsigned int v2
unsigned int v1
unsigned int v4
unsigned int v3
unsigned int e
unsigned int v
short mat_nr
float co[3]
Definition: BKE_main.h:116
struct BMEditMesh * edit_mesh
struct CustomData pdata ldata
struct MVert * mvert
struct Material ** mat
struct MDeformVert * dvert
int totedge
char cd_flag
char editflag
int totvert
struct MLoop * mloop
int totface
int totpoly
short totcol
int totloop
struct Key * key
struct MFace * mface
struct MPoly * mpoly
intptr_t * index_lookup
Definition: ED_mesh.h:329
ustring name
Definition: node.h:174
ListBase defbase
struct Material ** mat
char * matbits
unsigned short actfmap
float parentinv[4][4]
unsigned short actdef
float obmat[4][4]
struct Object * parent
void * data
ListBase fmaps
const float * mval_f
Definition: meshtools.c:1373
const MVert * mvert
Definition: meshtools.c:1372
ARegion * region
Definition: meshtools.c:1374
float len_best
Definition: meshtools.c:1377
struct Depsgraph * depsgraph
Definition: ED_view3d.h:75
struct ARegion * region
Definition: ED_view3d.h:80
struct View3D * v3d
Definition: ED_view3d.h:81
struct bDeformGroup * next
struct ReportList * reports
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
uint len
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3157