Blender V5.0
mball_tessellate.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cctype>
10#include <cfloat>
11#include <cmath>
12#include <cstdio>
13#include <cstdlib>
14#include <cstring>
15
16#include "MEM_guardedalloc.h"
17
18#include "DNA_meta_types.h"
19#include "DNA_object_types.h"
20#include "DNA_scene_types.h"
21
22#include "BLI_listbase.h"
23#include "BLI_math_geom.h"
24#include "BLI_math_matrix.h"
25#include "BLI_math_rotation.h"
26#include "BLI_math_vector.h"
27#include "BLI_math_vector.hh"
28#include "BLI_memarena.h"
29#include "BLI_string_utils.hh"
30#include "BLI_utildefines.h"
31
32#include "BKE_global.hh"
33#include "BKE_mball_tessellate.hh" /* own include */
34#include "BKE_mesh.hh"
35#include "BKE_object.hh"
36#include "BKE_scene.hh"
37
38#include "DEG_depsgraph.hh"
40
41#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
42
43/* experimental (faster) normal calculation (see #103021) */
44#define USE_ACCUM_NORMAL
45
46#define MBALL_ARRAY_LEN_INIT 4096
47
48/* Data types */
49
51struct CORNER {
52 int i, j, k; /* (i, j, k) is index within lattice */
53 float co[3], value; /* location and function value */
55};
56
58struct CUBE {
59 int i, j, k; /* lattice location of cube */
60 CORNER *corners[8]; /* eight corners */
61};
62
64struct CUBES {
65 CUBE cube; /* a single cube */
66 CUBES *next; /* remaining elements */
67};
68
70struct CENTERLIST {
71 int i, j, k; /* cube location */
72 CENTERLIST *next; /* remaining elements */
73};
74
76struct EDGELIST {
77 int i1, j1, k1, i2, j2, k2; /* edge corner ids */
78 int vid; /* vertex id */
79 EDGELIST *next; /* remaining elements */
80};
81
83struct INTLIST {
84 int i; /* an integer */
85 INTLIST *next; /* remaining elements */
86};
87
89struct INTLISTS {
90 INTLIST *list; /* a list of integers */
91 INTLISTS *next; /* remaining elements */
92};
93
95struct Box {
96 float min[3], max[3];
97 const MetaElem *ml;
98};
99
100struct MetaballBVHNode { /* node */
101 Box bb[2]; /* AABB of children */
103};
104
106struct PROCESS {
107 float thresh, size; /* mball threshold, single cube size */
108 float delta; /* small delta for calculating normals */
109 uint converge_res; /* converge procedure resolution (more = slower) */
110
111 MetaElem **mainb; /* array of all meta-elems. */
112 uint totelem, mem; /* number of meta-elems. */
113
114 MetaballBVHNode metaball_bvh; /* The simplest bvh */
115 Box allbb; /* Bounding box of all meta-elems */
116
117 MetaballBVHNode **bvh_queue; /* Queue used during bvh traversal */
119
120 CUBES *cubes; /* stack of cubes waiting for polygonization */
121 CENTERLIST **centers; /* cube center hash table */
122 CORNER **corners; /* corner value hash table */
123 EDGELIST **edges; /* edge and vertex id hash table */
124
125 int (*indices)[4]; /* output indices */
126 uint totindex; /* size of memory allocated for indices */
127 uint curindex; /* number of currently added indices */
128
129 blender::Vector<blender::float3> co; /* surface vertices positions */
130 blender::Vector<blender::float3> no; /* surface vertex normals */
131
132 /* memory allocation from common pool */
134};
135
136/* Forward declarations */
137static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2);
138static void add_cube(PROCESS *process, int i, int j, int k);
139static void make_face(PROCESS *process, int i1, int i2, int i3, int i4);
140static void converge(PROCESS *process, const CORNER *c1, const CORNER *c2, float r_p[3]);
141
142/* ******************* SIMPLE BVH ********************* */
143
144static void make_box_union(const BoundBox *a, const Box *b, Box *r_out)
145{
146 r_out->min[0] = min_ff(a->vec[0][0], b->min[0]);
147 r_out->min[1] = min_ff(a->vec[0][1], b->min[1]);
148 r_out->min[2] = min_ff(a->vec[0][2], b->min[2]);
149
150 r_out->max[0] = max_ff(a->vec[6][0], b->max[0]);
151 r_out->max[1] = max_ff(a->vec[6][1], b->max[1]);
152 r_out->max[2] = max_ff(a->vec[6][2], b->max[2]);
153}
154
155static void make_box_from_metaelem(Box *r, const MetaElem *ml)
156{
157 copy_v3_v3(r->max, ml->bb->vec[6]);
158 copy_v3_v3(r->min, ml->bb->vec[0]);
159 r->ml = ml;
160}
161
167static uint partition_mainb(MetaElem **mainb, uint start, uint end, uint s, float div)
168{
169 uint i = start, j = end - 1;
170 div *= 2.0f;
171
172 while (true) {
173 while (i < j && div > (mainb[i]->bb->vec[6][s] + mainb[i]->bb->vec[0][s])) {
174 i++;
175 }
176 while (j > i && div < (mainb[j]->bb->vec[6][s] + mainb[j]->bb->vec[0][s])) {
177 j--;
178 }
179
180 if (i >= j) {
181 break;
182 }
183
184 std::swap(mainb[i], mainb[j]);
185 i++;
186 j--;
187 }
188
189 if (i == start) {
190 i++;
191 }
192
193 return i;
194}
195
200 PROCESS *process, MetaballBVHNode *node, uint start, uint end, const Box *allbox)
201{
202 uint part, j, s;
203 float dim[3], div;
204
205 /* Maximum bvh queue size is number of nodes which are made, equals calls to this function. */
206 process->bvh_queue_size++;
207
208 dim[0] = allbox->max[0] - allbox->min[0];
209 dim[1] = allbox->max[1] - allbox->min[1];
210 dim[2] = allbox->max[2] - allbox->min[2];
211
212 s = 0;
213 if (dim[1] > dim[0] && dim[1] > dim[2]) {
214 s = 1;
215 }
216 else if (dim[2] > dim[1] && dim[2] > dim[0]) {
217 s = 2;
218 }
219
220 div = allbox->min[s] + (dim[s] / 2.0f);
221
222 part = partition_mainb(process->mainb, start, end, s, div);
223
224 make_box_from_metaelem(&node->bb[0], process->mainb[start]);
225 node->child[0] = nullptr;
226
227 if (part > start + 1) {
228 for (j = start; j < part; j++) {
229 make_box_union(process->mainb[j]->bb, &node->bb[0], &node->bb[0]);
230 }
231
232 node->child[0] = static_cast<MetaballBVHNode *>(
233 BLI_memarena_alloc(process->pgn_elements, sizeof(MetaballBVHNode)));
234 build_bvh_spatial(process, node->child[0], start, part, &node->bb[0]);
235 }
236
237 node->child[1] = nullptr;
238 if (part < end) {
239 make_box_from_metaelem(&node->bb[1], process->mainb[part]);
240
241 if (part < end - 1) {
242 for (j = part; j < end; j++) {
243 make_box_union(process->mainb[j]->bb, &node->bb[1], &node->bb[1]);
244 }
245
246 node->child[1] = static_cast<MetaballBVHNode *>(
247 BLI_memarena_alloc(process->pgn_elements, sizeof(MetaballBVHNode)));
248 build_bvh_spatial(process, node->child[1], part, end, &node->bb[1]);
249 }
250 }
251 else {
252 INIT_MINMAX(node->bb[1].min, node->bb[1].max);
253 }
254}
255
256/* ******************** ARITH ************************* */
257
270
271#define L 0 /* Left direction: -x, -i. */
272#define R 1 /* Right direction: +x, +i. */
273#define B 2 /* Bottom direction: -y, -j. */
274#define T 3 /* Top direction: +y, +j. */
275#define N 4 /* Near direction: -z, -k. */
276#define F 5 /* Far direction: +z, +k. */
277#define LBN 0 /* Left bottom near corner. */
278#define LBF 1 /* Left bottom far corner. */
279#define LTN 2 /* Left top near corner. */
280#define LTF 3 /* Left top far corner. */
281#define RBN 4 /* Right bottom near corner. */
282#define RBF 5 /* Right bottom far corner. */
283#define RTN 6 /* Right top near corner. */
284#define RTF 7 /* Right top far corner. */
285
290
291#define HASHBIT (5)
293#define HASHSIZE size_t(1 << (3 * HASHBIT))
294
295#define HASH(i, j, k) ((((((i) & 31) << 5) | ((j) & 31)) << 5) | ((k) & 31))
296
297#define MB_BIT(i, bit) (((i) >> (bit)) & 1)
298// #define FLIP(i, bit) ((i) ^ 1 << (bit)) /* flip the given bit of i */
299
300/* ******************** DENSITY COPMPUTATION ********************* */
301
310static float densfunc(const MetaElem *ball, float x, float y, float z)
311{
312 float dist2;
313 float dvec[3] = {x, y, z};
314
315 mul_m4_v3((const float (*)[4])ball->imat, dvec);
316
317 switch (ball->type) {
318 case MB_BALL:
319 /* do nothing */
320 break;
321 case MB_CUBE:
322 if (dvec[2] > ball->expz) {
323 dvec[2] -= ball->expz;
324 }
325 else if (dvec[2] < -ball->expz) {
326 dvec[2] += ball->expz;
327 }
328 else {
329 dvec[2] = 0.0;
330 }
332 case MB_PLANE:
333 if (dvec[1] > ball->expy) {
334 dvec[1] -= ball->expy;
335 }
336 else if (dvec[1] < -ball->expy) {
337 dvec[1] += ball->expy;
338 }
339 else {
340 dvec[1] = 0.0;
341 }
343 case MB_TUBE:
344 if (dvec[0] > ball->expx) {
345 dvec[0] -= ball->expx;
346 }
347 else if (dvec[0] < -ball->expx) {
348 dvec[0] += ball->expx;
349 }
350 else {
351 dvec[0] = 0.0;
352 }
353 break;
354 case MB_ELIPSOID:
355 dvec[0] /= ball->expx;
356 dvec[1] /= ball->expy;
357 dvec[2] /= ball->expz;
358 break;
359
360 /* *** deprecated, could be removed?, do-versioned at least *** */
361 case MB_TUBEX:
362 if (dvec[0] > ball->len) {
363 dvec[0] -= ball->len;
364 }
365 else if (dvec[0] < -ball->len) {
366 dvec[0] += ball->len;
367 }
368 else {
369 dvec[0] = 0.0;
370 }
371 break;
372 case MB_TUBEY:
373 if (dvec[1] > ball->len) {
374 dvec[1] -= ball->len;
375 }
376 else if (dvec[1] < -ball->len) {
377 dvec[1] += ball->len;
378 }
379 else {
380 dvec[1] = 0.0;
381 }
382 break;
383 case MB_TUBEZ:
384 if (dvec[2] > ball->len) {
385 dvec[2] -= ball->len;
386 }
387 else if (dvec[2] < -ball->len) {
388 dvec[2] += ball->len;
389 }
390 else {
391 dvec[2] = 0.0;
392 }
393 break;
394 /* *** end deprecated *** */
395 }
396
397 /* ball->rad2 is inverse of squared rad */
398 dist2 = 1.0f - (len_squared_v3(dvec) * ball->rad2);
399
400 /* ball->s is negative if metaball is negative */
401 return (dist2 < 0.0f) ? 0.0f : (ball->s * dist2 * dist2 * dist2);
402}
403
408static float metaball(PROCESS *process, float x, float y, float z)
409{
410 float dens = 0.0f;
411 uint front = 0, back = 0;
412 MetaballBVHNode *node;
413
414 process->bvh_queue[front++] = &process->metaball_bvh;
415
416 while (front != back) {
417 node = process->bvh_queue[back++];
418
419 for (int i = 0; i < 2; i++) {
420 if ((node->bb[i].min[0] <= x) && (node->bb[i].max[0] >= x) && (node->bb[i].min[1] <= y) &&
421 (node->bb[i].max[1] >= y) && (node->bb[i].min[2] <= z) && (node->bb[i].max[2] >= z))
422 {
423 if (node->child[i]) {
424 process->bvh_queue[front++] = node->child[i];
425 }
426 else {
427 dens += densfunc(node->bb[i].ml, x, y, z);
428 }
429 }
430 }
431 }
432
433 return process->thresh - dens;
434}
435
439static void make_face(PROCESS *process, int i1, int i2, int i3, int i4)
440{
441#ifdef USE_ACCUM_NORMAL
442 float n[3];
443#endif
444
445 if (UNLIKELY(process->totindex == process->curindex)) {
446 process->totindex = process->totindex ? (process->totindex * 2) : MBALL_ARRAY_LEN_INIT;
447 process->indices = static_cast<int (*)[4]>(
448 MEM_reallocN(process->indices, sizeof(int[4]) * process->totindex));
449 }
450
451 int *cur = process->indices[process->curindex++];
452
453 /* Treat triangles as fake quads. */
454 cur[0] = i1;
455 cur[1] = i2;
456 cur[2] = i3;
457 cur[3] = i4;
458
459#ifdef USE_ACCUM_NORMAL
460 if (i4 == i3) {
461 normal_tri_v3(n, process->co[i1], process->co[i2], process->co[i3]);
463 process->no[i2],
464 process->no[i3],
465 nullptr,
466 n,
467 process->co[i1],
468 process->co[i2],
469 process->co[i3],
470 nullptr);
471 }
472 else {
473 normal_quad_v3(n, process->co[i1], process->co[i2], process->co[i3], process->co[i4]);
475 process->no[i2],
476 process->no[i3],
477 process->no[i4],
478 n,
479 process->co[i1],
480 process->co[i2],
481 process->co[i3],
482 process->co[i4]);
483 }
484#endif
485}
486
487/* Frees allocated memory */
489{
490 if (process->corners) {
491 MEM_freeN(process->corners);
492 }
493 if (process->edges) {
494 MEM_freeN(process->edges);
495 }
496 if (process->centers) {
497 MEM_freeN(process->centers);
498 }
499 if (process->mainb) {
500 MEM_freeN(process->mainb);
501 }
502 if (process->bvh_queue) {
503 MEM_freeN(process->bvh_queue);
504 }
505 if (process->pgn_elements) {
506 BLI_memarena_free(process->pgn_elements);
507 }
508}
509
510/* **************** POLYGONIZATION ************************ */
511
512/**** Cubical Polygonization (optional) ****/
513
514#define LB 0 /* left bottom edge */
515#define LT 1 /* left top edge */
516#define LN 2 /* left near edge */
517#define LF 3 /* left far edge */
518#define RB 4 /* right bottom edge */
519#define RT 5 /* right top edge */
520#define RN 6 /* right near edge */
521#define RF 7 /* right far edge */
522#define BN 8 /* bottom near edge */
523#define BF 9 /* bottom far edge */
524#define TN 10 /* top near edge */
525#define TF 11 /* top far edge */
526
527static INTLISTS *cubetable[256];
528static char faces[256];
529
530/* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */
531static int corner1[12] = {
532 LBN,
533 LTN,
534 LBN,
535 LBF,
536 RBN,
537 RTN,
538 RBN,
539 RBF,
540 LBN,
541 LBF,
542 LTN,
543 LTF,
544};
545static int corner2[12] = {
546 LBF,
547 LTF,
548 LTN,
549 LTF,
550 RBF,
551 RTF,
552 RTN,
553 RTF,
554 RBN,
555 RBF,
556 RTN,
557 RTF,
558};
559static int leftface[12] = {
560 B,
561 L,
562 L,
563 F,
564 R,
565 T,
566 N,
567 R,
568 N,
569 B,
570 T,
571 F,
572};
573/* face on left when going corner1 to corner2 */
574static int rightface[12] = {
575 L,
576 T,
577 N,
578 L,
579 B,
580 R,
581 R,
582 F,
583 B,
584 F,
585 N,
586 T,
587};
588/* face on right when going corner1 to corner2 */
589
593static void docube(PROCESS *process, CUBE *cube)
594{
595 INTLISTS *polys;
596 CORNER *c1, *c2;
597 int i, index = 0, count, indexar[8];
598
599 /* Determine which case cube falls into. */
600 for (i = 0; i < 8; i++) {
601 if (cube->corners[i]->value > 0.0f) {
602 index += (1 << i);
603 }
604 }
605
606 /* Using faces[] table, adds neighboring cube if surface intersects face in this direction. */
607 if (MB_BIT(faces[index], 0)) {
608 add_cube(process, cube->i - 1, cube->j, cube->k);
609 }
610 if (MB_BIT(faces[index], 1)) {
611 add_cube(process, cube->i + 1, cube->j, cube->k);
612 }
613 if (MB_BIT(faces[index], 2)) {
614 add_cube(process, cube->i, cube->j - 1, cube->k);
615 }
616 if (MB_BIT(faces[index], 3)) {
617 add_cube(process, cube->i, cube->j + 1, cube->k);
618 }
619 if (MB_BIT(faces[index], 4)) {
620 add_cube(process, cube->i, cube->j, cube->k - 1);
621 }
622 if (MB_BIT(faces[index], 5)) {
623 add_cube(process, cube->i, cube->j, cube->k + 1);
624 }
625
626 /* Using cubetable[], determines polygons for output. */
627 for (polys = cubetable[index]; polys; polys = polys->next) {
628 INTLIST *edges;
629
630 count = 0;
631 /* Sets needed vertex id's lying on the edges. */
632 for (edges = polys->list; edges; edges = edges->next) {
633 c1 = cube->corners[corner1[edges->i]];
634 c2 = cube->corners[corner2[edges->i]];
635
636 indexar[count] = vertid(process, c1, c2);
637 count++;
638 }
639
640 /* Adds faces to output. */
641 if (count > 2) {
642 switch (count) {
643 case 3:
644 make_face(process, indexar[2], indexar[1], indexar[0], indexar[0]); /* triangle */
645 break;
646 case 4:
647 make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]);
648 break;
649 case 5:
650 make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]);
651 make_face(process, indexar[4], indexar[3], indexar[0], indexar[0]); /* triangle */
652 break;
653 case 6:
654 make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]);
655 make_face(process, indexar[5], indexar[4], indexar[3], indexar[0]);
656 break;
657 case 7:
658 make_face(process, indexar[3], indexar[2], indexar[1], indexar[0]);
659 make_face(process, indexar[5], indexar[4], indexar[3], indexar[0]);
660 make_face(process, indexar[6], indexar[5], indexar[0], indexar[0]); /* triangle */
661 break;
662 }
663 }
664 }
665}
666
671static CORNER *setcorner(PROCESS *process, int i, int j, int k)
672{
673 /* for speed, do corner value caching here */
674 CORNER *c;
675 int index;
676
677 /* does corner exist? */
678 index = HASH(i, j, k);
679 c = process->corners[index];
680
681 for (; c != nullptr; c = c->next) {
682 if (c->i == i && c->j == j && c->k == k) {
683 return c;
684 }
685 }
686
687 c = static_cast<CORNER *>(BLI_memarena_alloc(process->pgn_elements, sizeof(CORNER)));
688
689 c->i = i;
690 c->co[0] = (float(i) - 0.5f) * process->size;
691 c->j = j;
692 c->co[1] = (float(j) - 0.5f) * process->size;
693 c->k = k;
694 c->co[2] = (float(k) - 0.5f) * process->size;
695
696 c->value = metaball(process, c->co[0], c->co[1], c->co[2]);
697
698 c->next = process->corners[index];
699 process->corners[index] = c;
700
701 return c;
702}
703
707static int nextcwedge(int edge, int face)
708{
709 switch (edge) {
710 case LB:
711 return (face == L) ? LF : BN;
712 case LT:
713 return (face == L) ? LN : TF;
714 case LN:
715 return (face == L) ? LB : TN;
716 case LF:
717 return (face == L) ? LT : BF;
718 case RB:
719 return (face == R) ? RN : BF;
720 case RT:
721 return (face == R) ? RF : TN;
722 case RN:
723 return (face == R) ? RT : BN;
724 case RF:
725 return (face == R) ? RB : TF;
726 case BN:
727 return (face == B) ? RB : LN;
728 case BF:
729 return (face == B) ? LB : RF;
730 case TN:
731 return (face == T) ? LT : RN;
732 case TF:
733 return (face == T) ? RT : LF;
734 }
735 return 0;
736}
737
741static int otherface(int edge, int face)
742{
743 int other = leftface[edge];
744 return face == other ? rightface[edge] : other;
745}
746
750static void makecubetable()
751{
752 static bool is_done = false;
753 int i, e, c, done[12], pos[8];
754
755 if (is_done) {
756 return;
757 }
758 is_done = true;
759
760 for (i = 0; i < 256; i++) {
761 for (e = 0; e < 12; e++) {
762 done[e] = 0;
763 }
764 for (c = 0; c < 8; c++) {
765 pos[c] = MB_BIT(i, c);
766 }
767 for (e = 0; e < 12; e++) {
768 if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) {
769 INTLIST *ints = nullptr;
770 INTLISTS *lists = MEM_callocN<INTLISTS>("mball_intlist");
771 int start = e, edge = e;
772
773 /* get face that is to right of edge from pos to neg corner: */
774 int face = pos[corner1[e]] ? rightface[e] : leftface[e];
775
776 while (true) {
777 edge = nextcwedge(edge, face);
778 done[edge] = 1;
779 if (pos[corner1[edge]] != pos[corner2[edge]]) {
780 INTLIST *tmp = ints;
781
782 ints = MEM_callocN<INTLIST>("mball_intlist");
783 ints->i = edge;
784 ints->next = tmp; /* add edge to head of list */
785
786 if (edge == start) {
787 break;
788 }
789 face = otherface(edge, face);
790 }
791 }
792 lists->list = ints; /* add ints to head of table entry */
793 lists->next = cubetable[i];
794 cubetable[i] = lists;
795 }
796 }
797 }
798
799 for (i = 0; i < 256; i++) {
800 INTLISTS *polys;
801 faces[i] = 0;
802 for (polys = cubetable[i]; polys; polys = polys->next) {
803 INTLIST *edges;
804
805 for (edges = polys->list; edges; edges = edges->next) {
806 if (ELEM(edges->i, LB, LT, LN, LF)) {
807 faces[i] |= 1 << L;
808 }
809 if (ELEM(edges->i, RB, RT, RN, RF)) {
810 faces[i] |= 1 << R;
811 }
812 if (ELEM(edges->i, LB, RB, BN, BF)) {
813 faces[i] |= 1 << B;
814 }
815 if (ELEM(edges->i, LT, RT, TN, TF)) {
816 faces[i] |= 1 << T;
817 }
818 if (ELEM(edges->i, LN, RN, BN, TN)) {
819 faces[i] |= 1 << N;
820 }
821 if (ELEM(edges->i, LF, RF, BF, TF)) {
822 faces[i] |= 1 << F;
823 }
824 }
825 }
826 }
827}
828
830{
831 for (int i = 0; i < 256; i++) {
832 INTLISTS *lists = cubetable[i];
833 while (lists) {
834 INTLISTS *nlists = lists->next;
835
836 INTLIST *ints = lists->list;
837 while (ints) {
838 INTLIST *nints = ints->next;
839 MEM_freeN(ints);
840 ints = nints;
841 }
842
843 MEM_freeN(lists);
844 lists = nlists;
845 }
846 cubetable[i] = nullptr;
847 }
848}
849
850/**** Storage ****/
851
855static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k)
856{
857 int index;
858 CENTERLIST *newc, *l, *q;
859
860 index = HASH(i, j, k);
861 q = table[index];
862
863 for (l = q; l != nullptr; l = l->next) {
864 if (l->i == i && l->j == j && l->k == k) {
865 return 1;
866 }
867 }
868
869 newc = static_cast<CENTERLIST *>(BLI_memarena_alloc(process->pgn_elements, sizeof(CENTERLIST)));
870 newc->i = i;
871 newc->j = j;
872 newc->k = k;
873 newc->next = q;
874 table[index] = newc;
875
876 return 0;
877}
878
882static void setedge(PROCESS *process, int i1, int j1, int k1, int i2, int j2, int k2, int vid)
883{
884 int index;
885 EDGELIST *newe;
886
887 if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) {
888 int t = i1;
889 i1 = i2;
890 i2 = t;
891 t = j1;
892 j1 = j2;
893 j2 = t;
894 t = k1;
895 k1 = k2;
896 k2 = t;
897 }
898 index = HASH(i1, j1, k1) + HASH(i2, j2, k2);
899 newe = static_cast<EDGELIST *>(BLI_memarena_alloc(process->pgn_elements, sizeof(EDGELIST)));
900
901 newe->i1 = i1;
902 newe->j1 = j1;
903 newe->k1 = k1;
904 newe->i2 = i2;
905 newe->j2 = j2;
906 newe->k2 = k2;
907 newe->vid = vid;
908 newe->next = process->edges[index];
909 process->edges[index] = newe;
910}
911
915static int getedge(EDGELIST *table[], int i1, int j1, int k1, int i2, int j2, int k2)
916{
917 EDGELIST *q;
918
919 if (i1 > i2 || (i1 == i2 && (j1 > j2 || (j1 == j2 && k1 > k2)))) {
920 int t = i1;
921 i1 = i2;
922 i2 = t;
923 t = j1;
924 j1 = j2;
925 j2 = t;
926 t = k1;
927 k1 = k2;
928 k2 = t;
929 }
930 q = table[HASH(i1, j1, k1) + HASH(i2, j2, k2)];
931 for (; q != nullptr; q = q->next) {
932 if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 && q->i2 == i2 && q->j2 == j2 && q->k2 == k2) {
933 return q->vid;
934 }
935 }
936 return -1;
937}
938
942static void addtovertices(PROCESS *process, const float v[3], const float no[3])
943{
944 process->co.append(v);
945 process->no.append(no);
946}
947
948#ifndef USE_ACCUM_NORMAL
954static void vnormal(PROCESS *process, const float point[3], float r_no[3])
955{
956 const float delta = process->delta;
957 const float f = metaball(process, point[0], point[1], point[2]);
958
959 r_no[0] = metaball(process, point[0] + delta, point[1], point[2]) - f;
960 r_no[1] = metaball(process, point[0], point[1] + delta, point[2]) - f;
961 r_no[2] = metaball(process, point[0], point[1], point[2] + delta) - f;
962}
963#endif /* !USE_ACCUM_NORMAL */
964
970static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2)
971{
972 float v[3], no[3];
973 int vid = getedge(process->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k);
974
975 if (vid != -1) {
976 return vid; /* previously computed */
977 }
978
979 converge(process, c1, c2, v); /* position */
980
981#ifdef USE_ACCUM_NORMAL
982 zero_v3(no);
983#else
984 vnormal(process, v, no);
985#endif
986
987 addtovertices(process, v, no); /* save vertex */
988 vid = int(process->co.size()) - 1;
989 setedge(process, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid);
990
991 return vid;
992}
993
998static void converge(PROCESS *process, const CORNER *c1, const CORNER *c2, float r_p[3])
999{
1000 float c1_value, c1_co[3];
1001 float c2_value, c2_co[3];
1002
1003 if (c1->value < c2->value) {
1004 c1_value = c2->value;
1005 copy_v3_v3(c1_co, c2->co);
1006 c2_value = c1->value;
1007 copy_v3_v3(c2_co, c1->co);
1008 }
1009 else {
1010 c1_value = c1->value;
1011 copy_v3_v3(c1_co, c1->co);
1012 c2_value = c2->value;
1013 copy_v3_v3(c2_co, c2->co);
1014 }
1015
1016 for (uint i = 0; i < process->converge_res; i++) {
1017 interp_v3_v3v3(r_p, c1_co, c2_co, 0.5f);
1018 float dens = metaball(process, r_p[0], r_p[1], r_p[2]);
1019
1020 if (dens > 0.0f) {
1021 c1_value = dens;
1022 copy_v3_v3(c1_co, r_p);
1023 }
1024 else {
1025 c2_value = dens;
1026 copy_v3_v3(c2_co, r_p);
1027 }
1028 }
1029
1030 float tmp = -c1_value / (c2_value - c1_value);
1031 interp_v3_v3v3(r_p, c1_co, c2_co, tmp);
1032}
1033
1037static void add_cube(PROCESS *process, int i, int j, int k)
1038{
1039 CUBES *ncube;
1040 int n;
1041
1042 /* test if cube has been found before */
1043 if (setcenter(process, process->centers, i, j, k) == 0) {
1044 /* push cube on stack: */
1045 ncube = static_cast<CUBES *>(BLI_memarena_alloc(process->pgn_elements, sizeof(CUBES)));
1046 ncube->next = process->cubes;
1047 process->cubes = ncube;
1048
1049 ncube->cube.i = i;
1050 ncube->cube.j = j;
1051 ncube->cube.k = k;
1052
1053 /* set corners of initial cube: */
1054 for (n = 0; n < 8; n++) {
1055 ncube->cube.corners[n] = setcorner(
1056 process, i + MB_BIT(n, 2), j + MB_BIT(n, 1), k + MB_BIT(n, 0));
1057 }
1058 }
1059}
1060
1061static void next_lattice(int r[3], const float pos[3], const float size)
1062{
1063 r[0] = int(ceil((pos[0] / size) + 0.5f));
1064 r[1] = int(ceil((pos[1] / size) + 0.5f));
1065 r[2] = int(ceil((pos[2] / size) + 0.5f));
1066}
1067static void prev_lattice(int r[3], const float pos[3], const float size)
1068{
1069 next_lattice(r, pos, size);
1070 r[0]--;
1071 r[1]--;
1072 r[2]--;
1073}
1074static void closest_latice(int r[3], const float pos[3], const float size)
1075{
1076 r[0] = int(floorf(pos[0] / size + 1.0f));
1077 r[1] = int(floorf(pos[1] / size + 1.0f));
1078 r[2] = int(floorf(pos[2] / size + 1.0f));
1079}
1080
1084static void find_first_points(PROCESS *process, const uint em)
1085{
1086 const MetaElem *ml;
1087 blender::int3 center, lbn, rtf, it, dir, add;
1088 float tmp[3], a, b;
1089
1090 ml = process->mainb[em];
1091
1092 mid_v3_v3v3(tmp, ml->bb->vec[0], ml->bb->vec[6]);
1093 closest_latice(center, tmp, process->size);
1094 prev_lattice(lbn, ml->bb->vec[0], process->size);
1095 next_lattice(rtf, ml->bb->vec[6], process->size);
1096
1097 for (dir[0] = -1; dir[0] <= 1; dir[0]++) {
1098 for (dir[1] = -1; dir[1] <= 1; dir[1]++) {
1099 for (dir[2] = -1; dir[2] <= 1; dir[2]++) {
1100 if (dir[0] == 0 && dir[1] == 0 && dir[2] == 0) {
1101 continue;
1102 }
1103
1104 copy_v3_v3_int(it, center);
1105
1106 b = setcorner(process, it[0], it[1], it[2])->value;
1107 do {
1108 it[0] += dir[0];
1109 it[1] += dir[1];
1110 it[2] += dir[2];
1111 a = b;
1112 b = setcorner(process, it[0], it[1], it[2])->value;
1113
1114 if (a * b < 0.0f) {
1115 add[0] = it[0] - dir[0];
1116 add[1] = it[1] - dir[1];
1117 add[2] = it[2] - dir[2];
1118 add = blender::math::min(add, it);
1119 add_cube(process, add[0], add[1], add[2]);
1120 break;
1121 }
1122 } while ((it[0] > lbn[0]) && (it[1] > lbn[1]) && (it[2] > lbn[2]) && (it[0] < rtf[0]) &&
1123 (it[1] < rtf[1]) && (it[2] < rtf[2]));
1124 }
1125 }
1126 }
1127}
1128
1136{
1137 CUBE c;
1138
1139 process->centers = MEM_calloc_arrayN<CENTERLIST *>(HASHSIZE, "mbproc->centers");
1140 process->corners = MEM_calloc_arrayN<CORNER *>(HASHSIZE, "mbproc->corners");
1141 process->edges = MEM_calloc_arrayN<EDGELIST *>(2 * HASHSIZE, "mbproc->edges");
1142 process->bvh_queue = MEM_calloc_arrayN<MetaballBVHNode *>(process->bvh_queue_size,
1143 "Metaball BVH Queue");
1144
1145 makecubetable();
1146
1147 for (uint i = 0; i < process->totelem; i++) {
1149 }
1150
1151 while (process->cubes != nullptr) {
1152 c = process->cubes->cube;
1153 process->cubes = process->cubes->next;
1154
1155 docube(process, &c);
1156 }
1157}
1158
1160{
1161 if (has_zero_axis_m4(bob->object_to_world().ptr())) {
1162 return true;
1163 }
1164 for (Object *pob = bob->parent; pob; pob = pob->parent) {
1165 if (has_zero_axis_m4(pob->object_to_world().ptr())) {
1166 return true;
1167 }
1168 }
1169 return false;
1170}
1171
1177static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Object *ob)
1178{
1179 Scene *sce_iter = scene;
1180 Base *base;
1181 Object *bob;
1182 int obnr;
1183 char obname[MAX_ID_NAME];
1184 SceneBaseIter iter;
1185 const eEvaluationMode deg_eval_mode = DEG_get_mode(depsgraph);
1186 const short parenting_dupli_transflag = (OB_DUPLIFACES | OB_DUPLIVERTS);
1187
1188 /* Copy object matrices to cope with duplicators from #BKE_scene_base_iter_next. */
1189 float obinv[4][4], obmat[4][4];
1190 copy_m4_m4(obmat, ob->object_to_world().ptr());
1191 invert_m4_m4(obinv, ob->object_to_world().ptr());
1192
1193 BLI_string_split_name_number(ob->id.name + 2, '.', obname, &obnr);
1194
1195 /* make main array */
1196 BKE_scene_base_iter_next(depsgraph, &iter, &sce_iter, 0, nullptr, nullptr);
1197 while (BKE_scene_base_iter_next(depsgraph, &iter, &sce_iter, 1, &base, &bob)) {
1198 if (bob->type != OB_MBALL) {
1199 continue;
1200 }
1201
1202 /* If this metaball is the original that's used for duplication, only have it visible when
1203 * the instancer is visible too. */
1204 if ((base->flag_legacy & OB_FROMDUPLI) == 0 && ob->parent != nullptr &&
1205 (ob->parent->transflag & parenting_dupli_transflag) != 0 &&
1206 (BKE_object_visibility(ob->parent, deg_eval_mode) & OB_VISIBLE_SELF) == 0)
1207 {
1208 continue;
1209 }
1210
1211 if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) {
1212 /* Pass. */
1213 }
1214 else {
1215 char name[MAX_ID_NAME];
1216 int nr;
1217 BLI_string_split_name_number(bob->id.name + 2, '.', name, &nr);
1218 if (!STREQ(obname, name)) {
1219 /* Not part of the mother-ball, continue. */
1220 continue;
1221 }
1222 }
1223
1224 /* When metaball object has zero scale, then MetaElem to this MetaBall
1225 * will not be put to `mainb` array. */
1226 if (object_has_zero_axis_matrix(bob)) {
1227 continue;
1228 }
1229
1230 const MetaBall *mb = static_cast<MetaBall *>(bob->data);
1231 LISTBASE_FOREACH (const MetaElem *, ml, (mb->editelems ? mb->editelems : &mb->elems)) {
1232 if (ml->flag & MB_HIDE) {
1233 continue;
1234 }
1235 float pos[4][4], rot[4][4];
1236 float expx, expy, expz;
1237 blender::float3 tempmin, tempmax;
1238
1239 /* make a copy because of duplicates */
1240 MetaElem *new_ml = static_cast<MetaElem *>(
1241 BLI_memarena_alloc(process->pgn_elements, sizeof(MetaElem)));
1242 *(new_ml) = *ml;
1243 new_ml->bb = static_cast<BoundBox *>(
1244 BLI_memarena_alloc(process->pgn_elements, sizeof(BoundBox)));
1245 new_ml->mat = static_cast<float *>(
1246 BLI_memarena_alloc(process->pgn_elements, sizeof(float[4][4])));
1247 new_ml->imat = static_cast<float *>(
1248 BLI_memarena_alloc(process->pgn_elements, sizeof(float[4][4])));
1249
1250 /* too big stiffness seems only ugly due to linear interpolation
1251 * no need to have possibility for too big stiffness */
1252 if (ml->s > 10.0f) {
1253 new_ml->s = 10.0f;
1254 }
1255 else {
1256 new_ml->s = ml->s;
1257 }
1258
1259 /* if metaball is negative, set stiffness negative */
1260 if (new_ml->flag & MB_NEGATIVE) {
1261 new_ml->s = -new_ml->s;
1262 }
1263
1264 /* Translation of MetaElem */
1265 unit_m4(pos);
1266 pos[3][0] = ml->x;
1267 pos[3][1] = ml->y;
1268 pos[3][2] = ml->z;
1269
1270 /* Rotation of MetaElem is stored in quat */
1271 quat_to_mat4(rot, ml->quat);
1272
1273 /* Matrix multiply is as follows:
1274 * basis object space ->
1275 * world ->
1276 * ml object space ->
1277 * position ->
1278 * rotation ->
1279 * ml local space
1280 */
1281 mul_m4_series((float (*)[4])new_ml->mat, obinv, bob->object_to_world().ptr(), pos, rot);
1282 /* ml local space -> basis object space */
1283 invert_m4_m4((float (*)[4])new_ml->imat, (float (*)[4])new_ml->mat);
1284
1285 /* rad2 is inverse of squared radius */
1286 new_ml->rad2 = 1 / (ml->rad * ml->rad);
1287
1288 /* initial dimensions = radius */
1289 expx = ml->rad;
1290 expy = ml->rad;
1291 expz = ml->rad;
1292
1293 switch (ml->type) {
1294 case MB_BALL:
1295 break;
1296 case MB_CUBE: /* cube is "expanded" by expz, expy and expx */
1297 expz += ml->expz;
1299 case MB_PLANE: /* plane is "expanded" by expy and expx */
1300 expy += ml->expy;
1302 case MB_TUBE: /* tube is "expanded" by expx */
1303 expx += ml->expx;
1304 break;
1305 case MB_ELIPSOID: /* ellipsoid is "stretched" by exp* */
1306 expx *= ml->expx;
1307 expy *= ml->expy;
1308 expz *= ml->expz;
1309 break;
1310 }
1311
1312 /* untransformed Bounding Box of MetaElem */
1313 /* TODO: its possible the elem type has been changed and the exp*
1314 * values can use a fallback. */
1315 copy_v3_fl3(new_ml->bb->vec[0], -expx, -expy, -expz); /* 0 */
1316 copy_v3_fl3(new_ml->bb->vec[1], +expx, -expy, -expz); /* 1 */
1317 copy_v3_fl3(new_ml->bb->vec[2], +expx, +expy, -expz); /* 2 */
1318 copy_v3_fl3(new_ml->bb->vec[3], -expx, +expy, -expz); /* 3 */
1319 copy_v3_fl3(new_ml->bb->vec[4], -expx, -expy, +expz); /* 4 */
1320 copy_v3_fl3(new_ml->bb->vec[5], +expx, -expy, +expz); /* 5 */
1321 copy_v3_fl3(new_ml->bb->vec[6], +expx, +expy, +expz); /* 6 */
1322 copy_v3_fl3(new_ml->bb->vec[7], -expx, +expy, +expz); /* 7 */
1323
1324 /* Transformation of meta-elem bounding-box. */
1325 for (uint i = 0; i < 8; i++) {
1326 mul_m4_v3((float (*)[4])new_ml->mat, new_ml->bb->vec[i]);
1327 }
1328
1329 /* Find max and min of transformed bounding-box. */
1330 INIT_MINMAX(tempmin, tempmax);
1331 for (uint i = 0; i < 8; i++) {
1332 blender::math::min_max(blender::float3(new_ml->bb->vec[i]), tempmin, tempmax);
1333 }
1334
1335 /* Set only point 0 and 6 - AABB of meta-elem. */
1336 copy_v3_v3(new_ml->bb->vec[0], tempmin);
1337 copy_v3_v3(new_ml->bb->vec[6], tempmax);
1338
1339 /* add new_ml to mainb[] */
1340 if (UNLIKELY(process->totelem == process->mem)) {
1341 process->mem = process->mem * 2 + 10;
1342 process->mainb = static_cast<MetaElem **>(
1343 MEM_reallocN(process->mainb, sizeof(MetaElem *) * process->mem));
1344 }
1345 process->mainb[process->totelem++] = new_ml;
1346 }
1347 }
1348
1349 /* Compute AABB of all meta-elems. */
1350 if (process->totelem > 0) {
1351 copy_v3_v3(process->allbb.min, process->mainb[0]->bb->vec[0]);
1352 copy_v3_v3(process->allbb.max, process->mainb[0]->bb->vec[6]);
1353 for (uint i = 1; i < process->totelem; i++) {
1354 make_box_union(process->mainb[i]->bb, &process->allbb, &process->allbb);
1355 }
1356 }
1357}
1358
1360{
1361 PROCESS process{};
1362 const bool is_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
1363
1364 MetaBall *mb = static_cast<MetaBall *>(ob->data);
1365
1366 process.thresh = mb->thresh;
1367
1368 if (process.thresh < 0.001f) {
1369 process.converge_res = 16;
1370 }
1371 else if (process.thresh < 0.01f) {
1372 process.converge_res = 8;
1373 }
1374 else if (process.thresh < 0.1f) {
1375 process.converge_res = 4;
1376 }
1377 else {
1378 process.converge_res = 2;
1379 }
1380
1381 if (!is_render && (mb->flag == MB_UPDATE_NEVER)) {
1382 return nullptr;
1383 }
1384 if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) {
1385 return nullptr;
1386 }
1387
1388 if (is_render) {
1389 process.size = mb->rendersize;
1390 }
1391 else {
1392 process.size = mb->wiresize;
1393 if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_HALFRES) {
1394 process.size *= 2.0f;
1395 }
1396 }
1397
1398 process.delta = process.size * 0.001f;
1399
1400 process.co.reserve(MBALL_ARRAY_LEN_INIT);
1401 process.no.reserve(MBALL_ARRAY_LEN_INIT);
1402 process.pgn_elements = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "Metaball memarena");
1403
1404 /* initialize all mainb (MetaElems) */
1405 init_meta(depsgraph, &process, scene, ob);
1406 if (process.totelem == 0) {
1408 return nullptr;
1409 }
1410
1411 build_bvh_spatial(&process, &process.metaball_bvh, 0, process.totelem, &process.allbb);
1412
1413 {
1414 /* Don't polygonize meta-balls with too high resolution (base meta-ball too small).
1415 * NOTE: Epsilon was 0.0001f but this was giving problems for blood animation for
1416 * the open movie "Sintel", using 0.00001f. */
1417 const float eps = 0.00001f;
1418 const blender::float4x4 &object_to_world = ob->object_to_world();
1419 for (int i = 0; i < 3; i++) {
1420 if (blender::math::length_squared(object_to_world[i].xyz()) <
1421 blender::math::square(eps * (process.allbb.max[i] - process.allbb.min[i])))
1422 {
1424 return nullptr;
1425 }
1426 }
1427 }
1428
1430 if (process.curindex == 0) {
1432 return nullptr;
1433 }
1434
1436
1437 int corners_num = 0;
1438 for (uint i = 0; i < process.curindex; i++) {
1439 const int *indices = process.indices[i];
1440 const int count = indices[2] != indices[3] ? 4 : 3;
1441 corners_num += count;
1442 }
1443
1444 Mesh *mesh = BKE_mesh_new_nomain(int(process.co.size()), 0, int(process.curindex), corners_num);
1445 mesh->vert_positions_for_write().copy_from(process.co);
1446 blender::MutableSpan<int> face_offsets = mesh->face_offsets_for_write();
1447 blender::MutableSpan<int> corner_verts = mesh->corner_verts_for_write();
1448
1449 int loop_offset = 0;
1450 for (int i = 0; i < mesh->faces_num; i++) {
1451 const int *indices = process.indices[i];
1452
1453 const int count = indices[2] != indices[3] ? 4 : 3;
1454 face_offsets[i] = loop_offset;
1455
1456 corner_verts[loop_offset] = indices[0];
1457 corner_verts[loop_offset + 1] = indices[1];
1458 corner_verts[loop_offset + 2] = indices[2];
1459 if (count == 4) {
1460 corner_verts[loop_offset + 3] = indices[3];
1461 }
1462
1463 loop_offset += count;
1464 }
1465 MEM_freeN(process.indices);
1466
1467 for (int i = 0; i < mesh->verts_num; i++) {
1468 normalize_v3(process.no[i]);
1469 }
1470 blender::bke::mesh_vert_normals_assign(*mesh, std::move(process.no));
1471
1472 blender::bke::mesh_calc_edges(*mesh, false, false);
1473
1474 return mesh;
1475}
@ G_TRANSFORM_OBJ
@ G_TRANSFORM_EDIT
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
General operations, lookup, etc. for blender objects.
@ OB_VISIBLE_SELF
int BKE_object_visibility(const Object *ob, int dag_eval_mode)
int BKE_scene_base_iter_next(Depsgraph *depsgraph, SceneBaseIter *iter, Scene **scene, int val, Base **base, Object **ob)
Definition scene.cc:2069
#define ATTR_FALLTHROUGH
#define LISTBASE_FOREACH(type, var, list)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition math_geom.cc:58
void accumulate_vertex_normals_v3(float n1[3], float n2[3], float n3[3], float n4[3], const float f_no[3], const float co1[3], const float co2[3], const float co3[3], const float co4[3])
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:41
bool has_zero_axis_m4(const float matrix[4][4])
void mul_m4_v3(const float M[4][4], float r[3])
#define mul_m4_series(...)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void unit_m4(float m[4][4])
void quat_to_mat4(float m[4][4], const float q[4])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_v3_int(int r[3], const int a[3])
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void zero_v3(float r[3])
MINLINE float normalize_v3(float n[3])
#define BLI_MEMARENA_STD_BUFSIZE
MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void BLI_memarena_free(MemArena *ma) ATTR_NONNULL(1)
void * BLI_memarena_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
size_t BLI_string_split_name_number(const char *name, char delim, char *r_name_left, int *r_number) ATTR_NONNULL(1
unsigned int uint
#define INIT_MINMAX(min, max)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
eEvaluationMode
@ DAG_EVAL_RENDER
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
#define MAX_ID_NAME
Definition DNA_ID.h:373
@ MB_NEGATIVE
@ MB_HIDE
@ MB_TUBEY
@ MB_PLANE
@ MB_ELIPSOID
@ MB_TUBE
@ MB_TUBEX
@ MB_CUBE
@ MB_TUBEZ
@ MB_BALL
@ MB_UPDATE_FAST
@ MB_UPDATE_NEVER
@ MB_UPDATE_HALFRES
Object is a sort of wrapper for general info.
@ OB_MBALL
@ OB_FROMDUPLI
@ OB_DUPLIFACES
@ OB_DUPLIVERTS
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void process(btMatrix3x3 &B, btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V)
Helper function of 3X3 SVD for processing 2X2 SVD.
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
nullptr float
#define rot(x, k)
static ushort indices[]
uint pos
#define ceil
int count
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define N
static void addtovertices(PROCESS *process, const float v[3], const float no[3])
static void makecubetable()
static int corner1[12]
#define RTN
#define T
#define B
static void closest_latice(int r[3], const float pos[3], const float size)
static void find_first_points(PROCESS *process, const uint em)
#define RB
#define TF
#define BN
static int rightface[12]
#define MBALL_ARRAY_LEN_INIT
#define HASHSIZE
static INTLISTS * cubetable[256]
static void polygonize(PROCESS *process)
#define LF
void BKE_mball_cubeTable_free()
#define RBN
#define F
#define RTF
static void make_box_from_metaelem(Box *r, const MetaElem *ml)
static bool object_has_zero_axis_matrix(const Object *bob)
static void docube(PROCESS *process, CUBE *cube)
static int getedge(EDGELIST *table[], int i1, int j1, int k1, int i2, int j2, int k2)
#define LTN
#define R
static void next_lattice(int r[3], const float pos[3], const float size)
static int leftface[12]
Mesh * BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
static void freepolygonize(PROCESS *process)
#define LTF
#define RF
static int nextcwedge(int edge, int face)
#define HASH(i, j, k)
#define LN
static CORNER * setcorner(PROCESS *process, int i, int j, int k)
static float metaball(PROCESS *process, float x, float y, float z)
#define LBF
static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Object *ob)
static int vertid(PROCESS *process, const CORNER *c1, const CORNER *c2)
#define L
#define LBN
static uint partition_mainb(MetaElem **mainb, uint start, uint end, uint s, float div)
#define LT
#define RBF
#define MB_BIT(i, bit)
#define BF
static int otherface(int edge, int face)
static void prev_lattice(int r[3], const float pos[3], const float size)
static void make_box_union(const BoundBox *a, const Box *b, Box *r_out)
#define LB
#define RN
static void add_cube(PROCESS *process, int i, int j, int k)
static void build_bvh_spatial(PROCESS *process, MetaballBVHNode *node, uint start, uint end, const Box *allbox)
#define RT
static void make_face(PROCESS *process, int i1, int i2, int i3, int i4)
static void setedge(PROCESS *process, int i1, int j1, int k1, int i2, int j2, int k2, int vid)
#define TN
static int setcenter(PROCESS *process, CENTERLIST *table[], const int i, const int j, const int k)
static float densfunc(const MetaElem *ball, float x, float y, float z)
static char faces[256]
static int corner2[12]
static void converge(PROCESS *process, const CORNER *c1, const CORNER *c2, float r_p[3])
#define G(x, y, z)
static void add(blender::Map< std::string, std::string > &messages, Message &msg)
Definition msgfmt.cc:222
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
void mesh_vert_normals_assign(Mesh &mesh, Span< float3 > vert_normals)
T length_squared(const VecBase< T, Size > &a)
T min(const T &a, const T &b)
void min_max(const T &value, T &min, T &max)
T square(const T &a)
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
const btScalar eps
Definition poly34.cpp:11
const char * name
#define floorf
short flag_legacy
float vec[8][3]
float max[3]
const MetaElem * ml
float min[3]
CENTERLIST * next
CORNER * next
float co[3]
CUBES * next
CORNER * corners[8]
EDGELIST * next
char name[258]
Definition DNA_ID.h:432
INTLIST * list
INTLISTS * next
INTLIST * next
int faces_num
int verts_num
ListBase elems
float rendersize
float wiresize
ListBase * editelems
float * imat
struct BoundBox * bb
float * mat
MetaballBVHNode * child[2]
short transflag
struct Object * parent
int(* indices)[4]
MetaElem ** mainb
CENTERLIST ** centers
EDGELIST ** edges
blender::Vector< blender::float3 > co
MetaballBVHNode metaball_bvh
blender::Vector< blender::float3 > no
CORNER ** corners
MetaballBVHNode ** bvh_queue
MemArena * pgn_elements
i
Definition text_draw.cc:230