diff options
author | Hans Goudey <h.goudey@me.com> | 2022-08-17 17:20:25 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-08-17 17:20:25 +0300 |
commit | eaa87101cd5a20e577748bfff95b7cb06b04dd4b (patch) | |
tree | 8243ee6bd1479299f23819ef2765720fc9a18889 /source/blender/blenkernel | |
parent | 71f091a631c2deae08ff289184f928538b527cb3 (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.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_lattice.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_mball.h | 21 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_mball_tessellate.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/displist.cc | 139 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/lattice.c | 15 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mball.cc | 129 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mball_tessellate.c | 80 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_convert.cc | 76 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object_dupli.cc | 9 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object_update.c | 12 |
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 <->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; |