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
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_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
269
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
289
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;
411 MetaballBVHNode *node;
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_UPDATE_FAST
@ MB_UPDATE_NEVER
@ MB_UPDATE_HALFRES
@ MB_TUBEY
@ MB_PLANE
@ MB_ELIPSOID
@ MB_TUBE
@ MB_TUBEX
@ MB_CUBE
@ MB_TUBEZ
@ MB_BALL
@ MB_NEGATIVE
@ MB_HIDE
Object is a sort of wrapper for general info.
@ OB_DUPLIFACES
@ OB_DUPLIVERTS
@ OB_FROMDUPLI
@ OB_MBALL
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
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
local_group_size(16, 16) .push_constant(Type b
#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)
static ushort indices[]
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 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: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)
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
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
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
float scale[3]
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