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