Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-08-17 17:20:25 +0300
committerHans Goudey <h.goudey@me.com>2022-08-17 17:20:25 +0300
commiteaa87101cd5a20e577748bfff95b7cb06b04dd4b (patch)
tree8243ee6bd1479299f23819ef2765720fc9a18889 /source/blender/blenkernel
parent71f091a631c2deae08ff289184f928538b527cb3 (diff)
Metaball: Evaluate metaball objects as mesh components
With the ultimate goal of simplifying drawing and evaluation, this patch makes the following changes and removes code: - Use `Mesh` instead of `DispList` for evaluated basis metaballs. - Remove all `DispList` drawing code, which is now unused. - Simplify code that converts evaluated metaballs to meshes. - Store the evaluated mesh in the evaluated geometry set. This has the following indirect benefits: - Evaluated meshes from metaball objects can be used in geometry nodes. - Renderers can ignore evaluated metaball objects completely - Cycles rendering no longer has to convert to mesh from `DispList`. - We get closer to removing `DispList` completely. - Optimizations to mesh rendering will also apply to metaball objects. The vertex normals on the evaluated mesh are technically invalid; the regular calculation wouldn't reproduce them. Metaball objects don't support modifiers though, so it shouldn't be a problem. Eventually we can support per-vertex custom normals (T93551). Differential Revision: https://developer.blender.org/D14593
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_displist.h5
-rw-r--r--source/blender/blenkernel/BKE_lattice.h1
-rw-r--r--source/blender/blenkernel/BKE_mball.h21
-rw-r--r--source/blender/blenkernel/BKE_mball_tessellate.h8
-rw-r--r--source/blender/blenkernel/BKE_mesh.h1
-rw-r--r--source/blender/blenkernel/intern/displist.cc139
-rw-r--r--source/blender/blenkernel/intern/lattice.c15
-rw-r--r--source/blender/blenkernel/intern/mball.cc129
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c80
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.cc76
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc9
-rw-r--r--source/blender/blenkernel/intern/object_update.c12
12 files changed, 144 insertions, 352 deletions
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index cdca740555a..6551e732300 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -24,8 +24,6 @@ enum {
DL_SURF = 2,
/** Triangles. */
DL_INDEX3 = 4,
- /** Quads, with support for triangles (when values of the 3rd and 4th indices match). */
- DL_INDEX4 = 5,
// DL_VERTCOL = 6, /* UNUSED */
/** Isolated points. */
DL_VERTS = 7,
@@ -62,15 +60,12 @@ typedef struct DispList {
} DispList;
DispList *BKE_displist_find(struct ListBase *lb, int type);
-void BKE_displist_normals_add(struct ListBase *lb);
-void BKE_displist_count(const struct ListBase *lb, int *totvert, int *totface, int *tottri);
void BKE_displist_free(struct ListBase *lb);
void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph,
const struct Scene *scene,
struct Object *ob,
bool for_render);
-void BKE_displist_make_mball(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
void BKE_curve_calc_modifiers_pre(struct Depsgraph *depsgraph,
const struct Scene *scene,
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 9fa59c9e81b..aa4b1c69d24 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -27,7 +27,6 @@ void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *
struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name);
void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du);
-bool object_deform_mball(struct Object *ob, struct ListBase *dispbase);
void outside_lattice(struct Lattice *lt);
float (*BKE_lattice_vert_coords_alloc(const struct Lattice *lt, int *r_vert_len))[3];
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index a23d010b51f..667a1044e7b 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -55,14 +55,6 @@ bool BKE_mball_is_basis(const struct Object *ob);
struct Object *BKE_mball_basis_find(struct Scene *scene, struct Object *ob);
/**
- * Compute bounding box of all meta-elements / meta-ball.
- *
- * Bounding box is computed from polygonized surface. \a ob is
- * basic meta-balls (with name `Meta` for example). All other meta-ball objects
- * (with names `Meta.001`, `Meta.002`, etc) are included in this bounding-box.
- */
-void BKE_mball_texspace_calc(struct Object *ob);
-/**
* Return or compute bounding-box for given meta-ball object.
*/
struct BoundBox *BKE_mball_boundbox_get(struct Object *ob);
@@ -110,18 +102,7 @@ bool BKE_mball_select_swap_multi_ex(struct Base **bases, int bases_len);
/* **** Depsgraph evaluation **** */
-struct Depsgraph;
-
-/* Draw Cache */
-
-enum {
- BKE_MBALL_BATCH_DIRTY_ALL = 0,
-};
-void BKE_mball_batch_cache_dirty_tag(struct MetaBall *mb, int mode);
-void BKE_mball_batch_cache_free(struct MetaBall *mb);
-
-extern void (*BKE_mball_batch_cache_dirty_tag_cb)(struct MetaBall *mb, int mode);
-extern void (*BKE_mball_batch_cache_free_cb)(struct MetaBall *mb);
+void BKE_mball_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h
index 2dc16dc64d6..0840c51bb4d 100644
--- a/source/blender/blenkernel/BKE_mball_tessellate.h
+++ b/source/blender/blenkernel/BKE_mball_tessellate.h
@@ -12,11 +12,11 @@ extern "C" {
struct Depsgraph;
struct Object;
struct Scene;
+struct Mesh;
-void BKE_mball_polygonize(struct Depsgraph *depsgraph,
- struct Scene *scene,
- struct Object *ob,
- struct ListBase *dispbase);
+struct Mesh *BKE_mball_polygonize(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob);
void BKE_mball_cubeTable_free(void);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index b9f6b4b73f3..8cf973b785c 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -193,7 +193,6 @@ void BKE_mesh_orco_ensure(struct Object *ob, struct Mesh *mesh);
struct Mesh *BKE_mesh_from_object(struct Object *ob);
void BKE_mesh_assign_object(struct Main *bmain, struct Object *ob, struct Mesh *me);
-void BKE_mesh_from_metaball(struct ListBase *lb, struct Mesh *me);
void BKE_mesh_to_curve_nurblist(const struct Mesh *me,
struct ListBase *nurblist,
int edge_users_test);
diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc
index 0b3ed584246..65f6dc174f7 100644
--- a/source/blender/blenkernel/intern/displist.cc
+++ b/source/blender/blenkernel/intern/displist.cc
@@ -34,10 +34,8 @@
#include "BKE_displist.h"
#include "BKE_geometry_set.hh"
#include "BKE_key.h"
-#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_mball.h"
-#include "BKE_mball_tessellate.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -86,120 +84,6 @@ DispList *BKE_displist_find(ListBase *lb, int type)
return nullptr;
}
-void BKE_displist_normals_add(ListBase *lb)
-{
- float *vdata, *ndata, nor[3];
- float *v1, *v2, *v3, *v4;
- float *n1, *n2, *n3, *n4;
- int a, b, p1, p2, p3, p4;
-
- LISTBASE_FOREACH (DispList *, dl, lb) {
- if (dl->type == DL_INDEX3) {
- if (dl->nors == nullptr) {
- dl->nors = (float *)MEM_callocN(sizeof(float[3]), __func__);
-
- if (dl->flag & DL_BACK_CURVE) {
- dl->nors[2] = -1.0f;
- }
- else {
- dl->nors[2] = 1.0f;
- }
- }
- }
- else if (dl->type == DL_SURF) {
- if (dl->nors == nullptr) {
- dl->nors = (float *)MEM_callocN(sizeof(float[3]) * dl->nr * dl->parts, __func__);
-
- vdata = dl->verts;
- ndata = dl->nors;
-
- for (a = 0; a < dl->parts; a++) {
-
- if (BKE_displist_surfindex_get(dl, a, &b, &p1, &p2, &p3, &p4) == 0) {
- break;
- }
-
- v1 = vdata + 3 * p1;
- n1 = ndata + 3 * p1;
- v2 = vdata + 3 * p2;
- n2 = ndata + 3 * p2;
- v3 = vdata + 3 * p3;
- n3 = ndata + 3 * p3;
- v4 = vdata + 3 * p4;
- n4 = ndata + 3 * p4;
-
- for (; b < dl->nr; b++) {
- normal_quad_v3(nor, v1, v3, v4, v2);
-
- add_v3_v3(n1, nor);
- add_v3_v3(n2, nor);
- add_v3_v3(n3, nor);
- add_v3_v3(n4, nor);
-
- v2 = v1;
- v1 += 3;
- v4 = v3;
- v3 += 3;
- n2 = n1;
- n1 += 3;
- n4 = n3;
- n3 += 3;
- }
- }
- a = dl->parts * dl->nr;
- v1 = ndata;
- while (a--) {
- normalize_v3(v1);
- v1 += 3;
- }
- }
- }
- }
-}
-
-void BKE_displist_count(const ListBase *lb, int *totvert, int *totface, int *tottri)
-{
- LISTBASE_FOREACH (const DispList *, dl, lb) {
- int vert_tot = 0;
- int face_tot = 0;
- int tri_tot = 0;
- bool cyclic_u = dl->flag & DL_CYCL_U;
- bool cyclic_v = dl->flag & DL_CYCL_V;
-
- switch (dl->type) {
- case DL_SURF: {
- int segments_u = dl->nr - (cyclic_u == false);
- int segments_v = dl->parts - (cyclic_v == false);
- vert_tot = dl->nr * dl->parts;
- face_tot = segments_u * segments_v;
- tri_tot = face_tot * 2;
- break;
- }
- case DL_INDEX3: {
- vert_tot = dl->nr;
- face_tot = dl->parts;
- tri_tot = face_tot;
- break;
- }
- case DL_INDEX4: {
- vert_tot = dl->nr;
- face_tot = dl->parts;
- tri_tot = face_tot * 2;
- break;
- }
- case DL_POLY:
- case DL_SEGM: {
- vert_tot = dl->nr * dl->parts;
- break;
- }
- }
-
- *totvert += vert_tot;
- *totface += face_tot;
- *tottri += tri_tot;
- }
-}
-
bool BKE_displist_surfindex_get(
const DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
{
@@ -625,27 +509,6 @@ float BKE_displist_calc_taper(
return displist_calc_taper(depsgraph, scene, taperobj, fac);
}
-void BKE_displist_make_mball(Depsgraph *depsgraph, Scene *scene, Object *ob)
-{
- if (!ob || ob->type != OB_MBALL) {
- return;
- }
-
- if (ob == BKE_mball_basis_find(scene, ob)) {
- if (ob->runtime.curve_cache) {
- BKE_displist_free(&(ob->runtime.curve_cache->disp));
- }
- else {
- ob->runtime.curve_cache = MEM_cnew<CurveCache>(__func__);
- }
-
- BKE_mball_polygonize(depsgraph, scene, ob, &ob->runtime.curve_cache->disp);
- BKE_mball_texspace_calc(ob);
-
- object_deform_mball(ob, &ob->runtime.curve_cache->disp);
- }
-}
-
static ModifierData *curve_get_tessellate_point(const Scene *scene,
const Object *ob,
const bool for_render,
@@ -1504,7 +1367,7 @@ void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
bool doit = false;
LISTBASE_FOREACH (const DispList *, dl, dispbase) {
- const int tot = (ELEM(dl->type, DL_INDEX3, DL_INDEX4)) ? dl->nr : dl->nr * dl->parts;
+ const int tot = dl->type == DL_INDEX3 ? dl->nr : dl->nr * dl->parts;
for (const int i : IndexRange(tot)) {
minmax_v3v3_v3(min, max, &dl->verts[i * 3]);
}
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index b5c025a40b6..6fb67711ae9 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -398,21 +398,6 @@ Lattice *BKE_lattice_add(Main *bmain, const char *name)
return lt;
}
-bool object_deform_mball(Object *ob, ListBase *dispbase)
-{
- if (ob->parent && ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
- DispList *dl;
-
- for (dl = dispbase->first; dl; dl = dl->next) {
- BKE_lattice_deform_coords(ob->parent, ob, (float(*)[3])dl->verts, dl->nr, 0, NULL, 1.0f);
- }
-
- return true;
- }
-
- return false;
-}
-
static BPoint *latt_bp(Lattice *lt, int u, int v, int w)
{
return &lt->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
diff --git a/source/blender/blenkernel/intern/mball.cc b/source/blender/blenkernel/intern/mball.cc
index 084fea6abbd..beed21dc3b7 100644
--- a/source/blender/blenkernel/intern/mball.cc
+++ b/source/blender/blenkernel/intern/mball.cc
@@ -25,6 +25,7 @@
#include "DNA_defaults.h"
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -41,11 +42,15 @@
#include "BKE_anim_data.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
+#include "BKE_geometry_set.hh"
#include "BKE_idtype.h"
+#include "BKE_lattice.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_material.h"
#include "BKE_mball.h"
+#include "BKE_mball_tessellate.h"
+#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_scene.h"
@@ -76,15 +81,12 @@ static void metaball_copy_data(Main *UNUSED(bmain),
metaball_dst->editelems = nullptr;
metaball_dst->lastelem = nullptr;
- metaball_dst->batch_cache = nullptr;
}
static void metaball_free_data(ID *id)
{
MetaBall *metaball = (MetaBall *)id;
- BKE_mball_batch_cache_free(metaball);
-
MEM_SAFE_FREE(metaball->mat);
BLI_freelistN(&metaball->elems);
@@ -111,7 +113,6 @@ static void metaball_blend_write(BlendWriter *writer, ID *id, const void *id_add
/* Must always be cleared (meta's don't have their own edit-data). */
mb->needs_flush_to_id = 0;
mb->lastelem = nullptr;
- mb->batch_cache = nullptr;
/* write LibData */
BLO_write_id_struct(writer, MetaBall, id_address, &mb->id);
@@ -144,7 +145,6 @@ static void metaball_blend_read_data(BlendDataReader *reader, ID *id)
mb->needs_flush_to_id = 0;
// mb->edit_elems.first = mb->edit_elems.last = nullptr;
mb->lastelem = nullptr;
- mb->batch_cache = nullptr;
}
static void metaball_blend_read_lib(BlendLibReader *reader, ID *id)
@@ -249,63 +249,36 @@ MetaElem *BKE_mball_element_add(MetaBall *mb, const int type)
return ml;
}
-void BKE_mball_texspace_calc(Object *ob)
-{
- DispList *dl;
- BoundBox *bb;
- float *data, min[3], max[3] /*, loc[3], size[3] */;
- int tot;
- bool do_it = false;
-
- if (ob->runtime.bb == nullptr) {
- ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
- }
- bb = ob->runtime.bb;
-
- /* Weird one, this. */
- // INIT_MINMAX(min, max);
- (min)[0] = (min)[1] = (min)[2] = 1.0e30f;
- (max)[0] = (max)[1] = (max)[2] = -1.0e30f;
-
- dl = static_cast<DispList *>(ob->runtime.curve_cache->disp.first);
- while (dl) {
- tot = dl->nr;
- if (tot) {
- do_it = true;
- }
- data = dl->verts;
- while (tot--) {
- /* Also weird... but longer. From utildefines. */
- minmax_v3v3_v3(min, max, data);
- data += 3;
- }
- dl = dl->next;
- }
-
- if (!do_it) {
- min[0] = min[1] = min[2] = -1.0f;
- max[0] = max[1] = max[2] = 1.0f;
- }
-
- BKE_boundbox_init_from_minmax(bb, min, max);
-
- bb->flag &= ~BOUNDBOX_DIRTY;
-}
BoundBox *BKE_mball_boundbox_get(Object *ob)
{
BLI_assert(ob->type == OB_MBALL);
-
- if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
+ if (ob->runtime.bb != NULL && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
return ob->runtime.bb;
}
+ if (ob->runtime.bb == NULL) {
+ ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
+ }
- /* This should always only be called with evaluated objects,
- * but currently RNA is a problem here... */
- if (ob->runtime.curve_cache != nullptr) {
- BKE_mball_texspace_calc(ob);
+ /* Expect that this function is only called for evaluated objects. */
+ const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
+ float min[3];
+ float max[3];
+ if (mesh_eval) {
+ INIT_MINMAX(min, max);
+ if (!BKE_mesh_minmax(mesh_eval, min, max)) {
+ copy_v3_fl(min, -1.0f);
+ copy_v3_fl(max, 1.0f);
+ }
+ }
+ else {
+ copy_v3_fl(min, 0.0f);
+ copy_v3_fl(max, 0.0f);
}
+ BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
+ ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
+
return ob->runtime.bb;
}
@@ -735,20 +708,44 @@ bool BKE_mball_select_swap_multi_ex(Base **bases, int bases_len)
/* **** Depsgraph evaluation **** */
-/* Draw Engine */
+void BKE_mball_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
+{
+ BLI_assert(ob->type == OB_MBALL);
-void (*BKE_mball_batch_cache_dirty_tag_cb)(MetaBall *mb, int mode) = nullptr;
-void (*BKE_mball_batch_cache_free_cb)(MetaBall *mb) = nullptr;
+ BKE_object_free_derived_caches(ob);
-void BKE_mball_batch_cache_dirty_tag(MetaBall *mb, int mode)
-{
- if (mb->batch_cache) {
- BKE_mball_batch_cache_dirty_tag_cb(mb, mode);
+ const Object *basis_object = BKE_mball_basis_find(scene, ob);
+ if (ob != basis_object) {
+ return;
}
-}
-void BKE_mball_batch_cache_free(MetaBall *mb)
-{
- if (mb->batch_cache) {
- BKE_mball_batch_cache_free_cb(mb);
+
+ Mesh *mesh = BKE_mball_polygonize(depsgraph, scene, ob);
+ if (mesh == NULL) {
+ return;
}
-}
+
+ const MetaBall *mball = static_cast<MetaBall *>(ob->data);
+ mesh->mat = static_cast<Material **>(MEM_dupallocN(mball->mat));
+ mesh->totcol = mball->totcol;
+
+ if (ob->parent && ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
+ int verts_num;
+ float(*positions)[3] = BKE_mesh_vert_coords_alloc(mesh, &verts_num);
+ BKE_lattice_deform_coords(ob->parent, ob, positions, verts_num, 0, NULL, 1.0f);
+ BKE_mesh_vert_coords_apply(mesh, positions);
+ MEM_freeN(positions);
+ }
+
+ ob->runtime.geometry_set_eval = new GeometrySet(GeometrySet::create_with_mesh(mesh));
+
+ if (ob->runtime.bb == NULL) {
+ ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
+ }
+ blender::float3 min(std::numeric_limits<float>::max());
+ blender::float3 max(-std::numeric_limits<float>::max());
+ if (!ob->runtime.geometry_set_eval->compute_boundbox_without_instances(&min, &max)) {
+ min = blender::float3(0);
+ max = blender::float3(0);
+ }
+ BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
+};
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index 54def0189b1..96b3681b333 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -14,6 +14,8 @@
#include "MEM_guardedalloc.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -24,10 +26,11 @@
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
-#include "BKE_global.h"
-
#include "BKE_displist.h"
+#include "BKE_global.h"
+#include "BKE_lib_id.h"
#include "BKE_mball_tessellate.h" /* own include */
+#include "BKE_mesh.h"
#include "BKE_object.h"
#include "BKE_scene.h"
@@ -1371,7 +1374,7 @@ static void init_meta(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Obje
}
}
-void BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase)
+Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
PROCESS process = {0};
const bool is_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
@@ -1394,10 +1397,10 @@ void BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBa
}
if (!is_render && (mb->flag == MB_UPDATE_NEVER)) {
- return;
+ return NULL;
}
if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) {
- return;
+ return NULL;
}
if (is_render) {
@@ -1418,7 +1421,7 @@ void BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBa
init_meta(depsgraph, &process, scene, ob);
if (process.totelem == 0) {
freepolygonize(&process);
- return;
+ return NULL;
}
build_bvh_spatial(&process, &process.metaball_bvh, 0, process.totelem, &process.allbb);
@@ -1430,40 +1433,63 @@ void BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBa
ob->scale[1] < 0.00001f * (process.allbb.max[1] - process.allbb.min[1]) ||
ob->scale[2] < 0.00001f * (process.allbb.max[2] - process.allbb.min[2])) {
freepolygonize(&process);
- return;
+ return NULL;
}
polygonize(&process);
if (process.curindex == 0) {
freepolygonize(&process);
- return;
+ return NULL;
}
- /* add resulting surface to displist */
+ freepolygonize(&process);
+
+ Mesh *mesh = (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)ob->data)->name + 2);
- /* Avoid over-allocation since this is stored in the displist. */
- if (process.curindex != process.totindex) {
- process.indices = MEM_reallocN(process.indices, sizeof(int[4]) * process.curindex);
+ mesh->totvert = (int)process.curvertex;
+ MVert *mvert = CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_DEFAULT, NULL, mesh->totvert);
+ for (int i = 0; i < mesh->totvert; i++) {
+ copy_v3_v3(mvert[i].co, process.co[i]);
+ mvert->bweight = 0;
+ mvert->flag = 0;
}
- if (process.curvertex != process.totvertex) {
- process.co = MEM_reallocN(process.co, process.curvertex * sizeof(float[3]));
- process.no = MEM_reallocN(process.no, process.curvertex * sizeof(float[3]));
+ MEM_freeN(process.co);
+
+ mesh->totpoly = (int)process.curindex;
+ MPoly *mpoly = CustomData_add_layer(&mesh->pdata, CD_MPOLY, CD_DEFAULT, NULL, mesh->totpoly);
+ MLoop *mloop = CustomData_add_layer(&mesh->ldata, CD_MLOOP, CD_DEFAULT, NULL, mesh->totpoly * 4);
+
+ int loop_offset = 0;
+ for (int i = 0; i < mesh->totpoly; i++) {
+ const int *indices = process.indices[i];
+
+ const int count = indices[2] != indices[3] ? 4 : 3;
+ mpoly[i].loopstart = loop_offset;
+ mpoly[i].totloop = count;
+ mpoly[i].flag = ME_SMOOTH;
+
+ mloop[loop_offset].v = (uint32_t)indices[0];
+ mloop[loop_offset + 1].v = (uint32_t)indices[1];
+ mloop[loop_offset + 2].v = (uint32_t)indices[2];
+ if (count == 4) {
+ mloop[loop_offset + 3].v = (uint32_t)indices[3];
+ }
+
+ loop_offset += count;
}
+ MEM_freeN(process.indices);
- DispList *dl = MEM_callocN(sizeof(DispList), "mballdisp");
- BLI_addtail(dispbase, dl);
- dl->type = DL_INDEX4;
- dl->nr = (int)process.curvertex;
- dl->parts = (int)process.curindex;
+ for (int i = 0; i < mesh->totvert; i++) {
+ normalize_v3(process.no[i]);
+ }
+ mesh->runtime.vert_normals = process.no;
+ BKE_mesh_vertex_normals_clear_dirty(mesh);
- dl->index = (int *)process.indices;
+ mesh->totloop = loop_offset;
- for (uint a = 0; a < process.curvertex; a++) {
- normalize_v3(process.no[a]);
- }
+ BKE_mesh_update_customdata_pointers(mesh, false);
- dl->verts = (float *)process.co;
- dl->nors = (float *)process.no;
+ BKE_mesh_calc_edges(mesh, false, false);
- freepolygonize(&process);
+ return mesh;
}
diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc
index 24b81bce784..3806ea76cfe 100644
--- a/source/blender/blenkernel/intern/mesh_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_convert.cc
@@ -72,61 +72,6 @@ using blender::Span;
static CLG_LogRef LOG = {"bke.mesh_convert"};
-void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
-{
- DispList *dl;
- MVert *mvert;
- MLoop *mloop, *allloop;
- MPoly *mpoly;
- int a, *index;
-
- dl = (DispList *)lb->first;
- if (dl == nullptr) {
- return;
- }
-
- if (dl->type == DL_INDEX4) {
- mvert = (MVert *)CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, nullptr, dl->nr);
- allloop = mloop = (MLoop *)CustomData_add_layer(
- &me->ldata, CD_MLOOP, CD_CALLOC, nullptr, dl->parts * 4);
- mpoly = (MPoly *)CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, nullptr, dl->parts);
- me->mvert = mvert;
- me->mloop = mloop;
- me->mpoly = mpoly;
- me->totvert = dl->nr;
- me->totpoly = dl->parts;
-
- for (const int i : IndexRange(dl->nr)) {
- copy_v3_v3(me->mvert[i].co, &dl->verts[3 * i]);
- }
-
- a = dl->parts;
- index = dl->index;
- while (a--) {
- int count = index[2] != index[3] ? 4 : 3;
-
- mloop[0].v = index[0];
- mloop[1].v = index[1];
- mloop[2].v = index[2];
- if (count == 4) {
- mloop[3].v = index[3];
- }
-
- mpoly->totloop = count;
- mpoly->loopstart = (int)(mloop - allloop);
- mpoly->flag = ME_SMOOTH;
-
- mpoly++;
- mloop += count;
- me->totloop += count;
- index += 4;
- }
-
- BKE_mesh_update_customdata_pointers(me, true);
- BKE_mesh_calc_edges(me, true, false);
- }
-}
-
/**
* Specialized function to use when we _know_ existing edges don't overlap with poly edges.
*/
@@ -929,32 +874,21 @@ static Mesh *mesh_new_from_curve_type_object(const Object *object)
static Mesh *mesh_new_from_mball_object(Object *object)
{
- MetaBall *mball = (MetaBall *)object->data;
-
/* NOTE: We can only create mesh for a polygonized meta ball. This figures out all original meta
* balls and all evaluated child meta balls (since polygonization is only stored in the mother
* ball).
*
* Create empty mesh so script-authors don't run into None objects. */
- if (!DEG_is_evaluated_object(object) || object->runtime.curve_cache == nullptr ||
- BLI_listbase_is_empty(&object->runtime.curve_cache->disp)) {
+ if (!DEG_is_evaluated_object(object)) {
return (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
}
- Mesh *mesh_result = (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
- BKE_mesh_from_metaball(&object->runtime.curve_cache->disp, mesh_result);
- BKE_mesh_texspace_copy_from_object(mesh_result, object);
-
- /* Copy materials. */
- mesh_result->totcol = mball->totcol;
- mesh_result->mat = (Material **)MEM_dupallocN(mball->mat);
- if (mball->mat != nullptr) {
- for (int i = mball->totcol; i-- > 0;) {
- mesh_result->mat[i] = BKE_object_material_get(object, i + 1);
- }
+ const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(object);
+ if (mesh_eval == nullptr) {
+ return (Mesh *)BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
}
- return mesh_result;
+ return BKE_mesh_copy_for_eval(mesh_eval, false);
}
static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh)
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index cc3a8b5bb0e..228bc682ddd 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -201,7 +201,7 @@ static DupliObject *make_dupli(
/* Meta-balls never draw in duplis, they are instead merged into one by the basis
* meta-ball outside of the group. this does mean that if that meta-ball is not in the
* scene, they will not show up at all, limitation that should be solved once. */
- if (ob->type == OB_MBALL) {
+ if (object_data && GS(object_data->name) == ID_MB) {
dob->no_draw = true;
}
@@ -1563,6 +1563,13 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
return nullptr;
}
+ /* Metaball objects can't create instances, but the dupli system is used to "instance" their
+ * evaluated mesh to render engines. We need to exit early to avoid recursively instancing the
+ * evaluated metaball mesh on metaball instances that already contribute to the basis. */
+ if (ctx->object->type == OB_MBALL && ctx->level > 0) {
+ return nullptr;
+ }
+
/* Should the dupli's be generated for this object? - Respect restrict flags. */
if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (visibility_flag & OB_HIDE_RENDER) :
(visibility_flag & OB_HIDE_VIEWPORT)) {
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index af0c5107348..5656a9f6c92 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -168,7 +168,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
break;
case OB_MBALL:
- BKE_displist_make_mball(depsgraph, scene, ob);
+ BKE_mball_data_update(depsgraph, scene, ob);
break;
case OB_CURVES_LEGACY:
@@ -292,9 +292,15 @@ void BKE_object_batch_cache_dirty_tag(Object *ob)
case OB_CURVES_LEGACY:
BKE_curve_batch_cache_dirty_tag((struct Curve *)ob->data, BKE_CURVE_BATCH_DIRTY_ALL);
break;
- case OB_MBALL:
- BKE_mball_batch_cache_dirty_tag((struct MetaBall *)ob->data, BKE_MBALL_BATCH_DIRTY_ALL);
+ case OB_MBALL: {
+ /* This function is currently called on original objects, so to properly
+ * clear the actual displayed geometry, we have to tag the evaluated mesh. */
+ Mesh *mesh = BKE_object_get_evaluated_mesh_no_subsurf(ob);
+ if (mesh) {
+ BKE_mesh_batch_cache_dirty_tag(mesh, BKE_MESH_BATCH_DIRTY_ALL);
+ }
break;
+ }
case OB_GPENCIL:
BKE_gpencil_batch_cache_dirty_tag((struct bGPdata *)ob->data);
break;