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
path: root/source
diff options
context:
space:
mode:
authorSybren A. Stüvel <sybren@stuvel.eu>2018-06-01 18:05:21 +0300
committerSybren A. Stüvel <sybren@stuvel.eu>2018-06-01 18:35:26 +0300
commitc0dd355926abd214570add8054e43a51af4e5b28 (patch)
tree9851393fb7fab6f928b7ac8a63bf70088d7187b9 /source
parent4fccb8a023c17abf6dae37e80aa835e2de39807b (diff)
Modifiers: ported applying modifier from DerivedMesh → Mesh
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_mesh.h14
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c347
-rw-r--r--source/blender/editors/object/object_modifier.c18
3 files changed, 370 insertions, 9 deletions
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index d3b492983de..efbc00c456f 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -34,6 +34,9 @@
/* defines BLI_INLINE */
#include "BLI_utildefines.h"
+/* defines CustomDataMask */
+#include "BKE_customdata.h"
+
struct ID;
struct BMeshCreateParams;
struct BMeshFromMeshParams;
@@ -46,9 +49,11 @@ struct LinkNode;
struct BLI_Stack;
struct MemArena;
struct BMesh;
+struct KeyBlock;
struct MLoopTri;
struct Main;
struct Mesh;
+struct ModifierData;
struct MPoly;
struct MLoop;
struct MFace;
@@ -168,6 +173,15 @@ void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
struct Mesh *BKE_mesh_new_from_object(
struct Depsgraph *depsgraph, struct Main *bmain, struct Scene *sce, struct Object *ob,
const bool apply_modifiers, const bool calc_tessface, const bool calc_undeformed);
+struct Mesh *BKE_mesh_create_derived_for_modifier(
+ struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob,
+ struct ModifierData *md, int build_shapekey_layers);
+
+/* Copies a nomain-Mesh into an existing Mesh. */
+void BKE_nomain_mesh_to_mesh(struct Mesh *mesh_src, struct Mesh *mesh_dst, struct Object *ob,
+ CustomDataMask mask, bool take_ownership);
+void BKE_nomain_mesh_to_meshkey(struct Mesh *mesh_src, struct Mesh *mesh_dst, struct KeyBlock *kb);
+
/* vertex level transformations & checks (no derived mesh) */
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index b2ff79cd933..a3eef7b17b2 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -26,6 +26,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
+#include "DNA_key_types.h"
#include "DNA_material_types.h"
#include "DNA_meta_types.h"
#include "DNA_object_types.h"
@@ -40,7 +41,9 @@
#include "BKE_main.h"
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
+#include "BKE_key.h"
#include "BKE_mesh.h"
+#include "BKE_modifier.h"
#include "BKE_displist.h"
#include "BKE_library.h"
#include "BKE_material.h"
@@ -58,6 +61,12 @@
*/
// #undef VALIDATE_MESH
+#ifdef VALIDATE_MESH
+# define ASSERT_IS_VALID_MESH(mesh) (BLI_assert((mesh == NULL) || (BKE_mesh_is_valid(mesh) == true)))
+#else
+# define ASSERT_IS_VALID_MESH(mesh)
+#endif
+
void BKE_mesh_from_metaball(ListBase *lb, Mesh *me)
{
DispList *dl;
@@ -1088,3 +1097,341 @@ Mesh *BKE_mesh_new_from_object(
return tmpmesh;
}
+
+
+static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src)
+{
+ KeyBlock *kb;
+ Key *key = mesh_src->key;
+ int i;
+
+ if (!mesh_src->key)
+ return;
+
+ /* ensure we can use mesh vertex count for derived mesh custom data */
+ if (mesh_src->totvert != mesh_dest->totvert) {
+ fprintf(stderr,
+ "%s: vertex size mismatch (mesh/dm) '%s' (%d != %d)\n",
+ __func__, mesh_src->id.name + 2, mesh_src->totvert, mesh_dest->totvert);
+ return;
+ }
+
+ for (i = 0, kb = key->block.first; kb; kb = kb->next, i++) {
+ int ci;
+ float *array;
+
+ if (mesh_src->totvert != kb->totelem) {
+ fprintf(stderr,
+ "%s: vertex size mismatch (Mesh '%s':%d != KeyBlock '%s':%d)\n",
+ __func__, mesh_src->id.name + 2, mesh_src->totvert, kb->name, kb->totelem);
+ array = MEM_calloc_arrayN((size_t)mesh_src->totvert, 3 * sizeof(float), __func__);
+ }
+ else {
+ array = MEM_malloc_arrayN((size_t)mesh_src->totvert, 3 * sizeof(float), __func__);
+ memcpy(array, kb->data, (size_t)mesh_src->totvert * 3 * sizeof(float));
+ }
+
+ CustomData_add_layer_named(&mesh_dest->vdata, CD_SHAPEKEY, CD_ASSIGN, array, mesh_dest->totvert, kb->name);
+ ci = CustomData_get_layer_index_n(&mesh_dest->vdata, CD_SHAPEKEY, i);
+
+ mesh_dest->vdata.layers[ci].uid = kb->uid;
+ }
+}
+
+
+Mesh *BKE_mesh_create_derived_for_modifier(
+ struct Depsgraph *depsgraph, Scene *scene, Object *ob,
+ ModifierData *md, int build_shapekey_layers)
+{
+ Mesh *me = ob->data;
+ const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ Mesh *result;
+ KeyBlock *kb;
+ ModifierEvalContext mectx = {depsgraph, ob, 0};
+
+ md->scene = scene;
+
+ if (!(md->mode & eModifierMode_Realtime)) {
+ return NULL;
+ }
+
+ if (mti->isDisabled && mti->isDisabled(md, 0)) {
+ return NULL;
+ }
+
+ if (build_shapekey_layers && me->key && (kb = BLI_findlink(&me->key->block, ob->shapenr - 1))) {
+ BKE_keyblock_convert_to_mesh(kb, me);
+ }
+
+ if (mti->type == eModifierTypeType_OnlyDeform) {
+ int numVerts;
+ float (*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts);
+
+ modifier_deformVerts(md, &mectx, NULL, deformedVerts, numVerts);
+ BKE_id_copy_ex(NULL, &me->id, (ID **)&result,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
+ BKE_mesh_apply_vert_coords(result, deformedVerts);
+
+ if (build_shapekey_layers)
+ add_shapekey_layers(result, me);
+
+ MEM_freeN(deformedVerts);
+ }
+ else {
+ Mesh *mesh_temp;
+ BKE_id_copy_ex(NULL, &me->id, (ID **)&mesh_temp,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
+
+ if (build_shapekey_layers)
+ add_shapekey_layers(mesh_temp, me);
+
+ result = modifier_applyModifier(md, &mectx, mesh_temp);
+ ASSERT_IS_VALID_MESH(result);
+
+ if (mesh_temp != result) {
+ BKE_id_free(NULL, mesh_temp);
+ }
+ }
+
+ return result;
+}
+
+/* This is a Mesh-based copy of the same function in DerivedMesh.c */
+static void shapekey_layers_to_keyblocks(Mesh *mesh_src, Mesh *mesh_dst, int actshape_uid)
+{
+ KeyBlock *kb;
+ int i, j, tot;
+
+ if (!mesh_dst->key)
+ return;
+
+ tot = CustomData_number_of_layers(&mesh_src->vdata, CD_SHAPEKEY);
+ for (i = 0; i < tot; i++) {
+ CustomDataLayer *layer = &mesh_src->vdata.layers[CustomData_get_layer_index_n(&mesh_src->vdata, CD_SHAPEKEY, i)];
+ float (*cos)[3], (*kbcos)[3];
+
+ for (kb = mesh_dst->key->block.first; kb; kb = kb->next) {
+ if (kb->uid == layer->uid)
+ break;
+ }
+
+ if (!kb) {
+ kb = BKE_keyblock_add(mesh_dst->key, layer->name);
+ kb->uid = layer->uid;
+ }
+
+ if (kb->data)
+ MEM_freeN(kb->data);
+
+ cos = CustomData_get_layer_n(&mesh_src->vdata, CD_SHAPEKEY, i);
+ kb->totelem = mesh_src->totvert;
+
+ kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, 3 * sizeof(float), "kbcos DerivedMesh.c");
+ if (kb->uid == actshape_uid) {
+ MVert *mvert = mesh_src->mvert;
+
+ for (j = 0; j < mesh_src->totvert; j++, kbcos++, mvert++) {
+ copy_v3_v3(*kbcos, mvert->co);
+ }
+ }
+ else {
+ for (j = 0; j < kb->totelem; j++, cos++, kbcos++) {
+ copy_v3_v3(*kbcos, *cos);
+ }
+ }
+ }
+
+ for (kb = mesh_dst->key->block.first; kb; kb = kb->next) {
+ if (kb->totelem != mesh_src->totvert) {
+ if (kb->data)
+ MEM_freeN(kb->data);
+
+ kb->totelem = mesh_src->totvert;
+ kb->data = MEM_calloc_arrayN(kb->totelem, 3 * sizeof(float), "kb->data derivedmesh.c");
+ fprintf(stderr, "%s: lost a shapekey layer: '%s'! (bmesh internal error)\n", __func__, kb->name);
+ }
+ }
+}
+
+
+/* This is a Mesh-based copy of DM_to_mesh() */
+void BKE_nomain_mesh_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob, CustomDataMask mask, bool take_ownership)
+{
+ /* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */
+ /* TODO(Sybren): the above claim came from DM_to_mesh(); check whether it is still true with Mesh */
+ Mesh tmp = *mesh_dst;
+ int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
+ int did_shapekeys = 0;
+ eCDAllocType alloctype = CD_DUPLICATE;
+
+ if (take_ownership /* && dm->type == DM_TYPE_CDDM && dm->needsFree */) {
+ bool has_any_referenced_layers =
+ CustomData_has_referenced(&mesh_src->vdata) ||
+ CustomData_has_referenced(&mesh_src->edata) ||
+ CustomData_has_referenced(&mesh_src->ldata) ||
+ CustomData_has_referenced(&mesh_src->fdata) ||
+ CustomData_has_referenced(&mesh_src->pdata);
+ if (!has_any_referenced_layers) {
+ alloctype = CD_ASSIGN;
+ }
+ }
+ CustomData_reset(&tmp.vdata);
+ CustomData_reset(&tmp.edata);
+ CustomData_reset(&tmp.fdata);
+ CustomData_reset(&tmp.ldata);
+ CustomData_reset(&tmp.pdata);
+
+ BKE_mesh_ensure_normals(mesh_src);
+
+ totvert = tmp.totvert = mesh_src->totvert;
+ totedge = tmp.totedge = mesh_src->totedge;
+ totloop = tmp.totloop = mesh_src->totloop;
+ totpoly = tmp.totpoly = mesh_src->totpoly;
+ tmp.totface = 0;
+
+ CustomData_copy(&mesh_src->vdata, &tmp.vdata, mask, alloctype, totvert);
+ CustomData_copy(&mesh_src->edata, &tmp.edata, mask, alloctype, totedge);
+ CustomData_copy(&mesh_src->ldata, &tmp.ldata, mask, alloctype, totloop);
+ CustomData_copy(&mesh_src->pdata, &tmp.pdata, mask, alloctype, totpoly);
+ tmp.cd_flag = mesh_src->cd_flag;
+ tmp.runtime.deformed_only = mesh_src->runtime.deformed_only;
+
+ if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) {
+ KeyBlock *kb;
+ int uid;
+
+ if (ob) {
+ kb = BLI_findlink(&mesh_dst->key->block, ob->shapenr - 1);
+ if (kb) {
+ uid = kb->uid;
+ }
+ else {
+ printf("%s: error - could not find active shapekey %d!\n",
+ __func__, ob->shapenr - 1);
+
+ uid = INT_MAX;
+ }
+ }
+ else {
+ /* if no object, set to INT_MAX so we don't mess up any shapekey layers */
+ uid = INT_MAX;
+ }
+
+ shapekey_layers_to_keyblocks(mesh_src, mesh_dst, uid);
+ did_shapekeys = 1;
+ }
+
+ /* copy texture space */
+ if (ob) {
+ BKE_mesh_texspace_copy_from_object(&tmp, ob);
+ }
+
+ /* not all DerivedMeshes store their verts/edges/faces in CustomData, so
+ * we set them here in case they are missing */
+ /* TODO(Sybren): we could probably replace CD_ASSIGN with alloctype and always directly pass mesh_src->mxxx,
+ * instead of using a ternary operator. */
+ if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) {
+ CustomData_add_layer(&tmp.vdata, CD_MVERT, CD_ASSIGN,
+ (alloctype == CD_ASSIGN) ? mesh_src->mvert : MEM_dupallocN(mesh_src->mvert),
+ totvert);
+ }
+ if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) {
+ CustomData_add_layer(&tmp.edata, CD_MEDGE, CD_ASSIGN,
+ (alloctype == CD_ASSIGN) ? mesh_src->medge : MEM_dupallocN(mesh_src->medge),
+ totedge);
+ }
+ if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) {
+ /* TODO(Sybren): assigment to tmp.mxxx is probably not necessary due to the
+ * BKE_mesh_update_customdata_pointers() call below. */
+ tmp.mloop = (alloctype == CD_ASSIGN) ? mesh_src->mloop : MEM_dupallocN(mesh_src->mloop);
+ tmp.mpoly = (alloctype == CD_ASSIGN) ? mesh_src->mpoly : MEM_dupallocN(mesh_src->mpoly);
+
+ CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop);
+ CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly);
+ }
+
+ /* object had got displacement layer, should copy this layer to save sculpted data */
+ /* NOTE: maybe some other layers should be copied? nazgul */
+ if (CustomData_has_layer(&mesh_dst->ldata, CD_MDISPS)) {
+ if (totloop == mesh_dst->totloop) {
+ MDisps *mdisps = CustomData_get_layer(&mesh_dst->ldata, CD_MDISPS);
+ CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop);
+ }
+ }
+
+ /* yes, must be before _and_ after tessellate */
+ BKE_mesh_update_customdata_pointers(&tmp, false);
+
+ /* since 2.65 caller must do! */
+ // BKE_mesh_tessface_calc(&tmp);
+
+ CustomData_free(&mesh_dst->vdata, mesh_dst->totvert);
+ CustomData_free(&mesh_dst->edata, mesh_dst->totedge);
+ CustomData_free(&mesh_dst->fdata, mesh_dst->totface);
+ CustomData_free(&mesh_dst->ldata, mesh_dst->totloop);
+ CustomData_free(&mesh_dst->pdata, mesh_dst->totpoly);
+
+ /* ok, this should now use new CD shapekey data,
+ * which should be fed through the modifier
+ * stack */
+ if (tmp.totvert != mesh_dst->totvert && !did_shapekeys && mesh_dst->key) {
+ printf("%s: YEEK! this should be recoded! Shape key loss!: ID '%s'\n", __func__, tmp.id.name);
+ if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) {
+ id_us_min(&tmp.key->id);
+ }
+ tmp.key = NULL;
+ }
+
+ /* Clear selection history */
+ MEM_SAFE_FREE(tmp.mselect);
+ tmp.totselect = 0;
+ BLI_assert(ELEM(tmp.bb, NULL, mesh_dst->bb));
+ if (mesh_dst->bb) {
+ MEM_freeN(mesh_dst->bb);
+ tmp.bb = NULL;
+ }
+
+ /* skip the listbase */
+ MEMCPY_STRUCT_OFS(mesh_dst, &tmp, id.prev);
+
+ if (take_ownership) {
+ if (alloctype == CD_ASSIGN) {
+ CustomData_free_typemask(&mesh_src->vdata, mesh_src->totvert, ~mask);
+ CustomData_free_typemask(&mesh_src->edata, mesh_src->totedge, ~mask);
+ CustomData_free_typemask(&mesh_src->ldata, mesh_src->totloop, ~mask);
+ CustomData_free_typemask(&mesh_src->pdata, mesh_src->totpoly, ~mask);
+ }
+ BKE_id_free(NULL, mesh_src);
+ }
+}
+
+/* This is a Mesh-based copy of DM_to_meshkey() */
+void BKE_nomain_mesh_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb)
+{
+ int a, totvert = mesh_src->totvert;
+ float *fp;
+ MVert *mvert;
+
+ if (totvert == 0 || mesh_dst->totvert == 0 || mesh_dst->totvert != totvert) {
+ return;
+ }
+
+ if (kb->data) MEM_freeN(kb->data);
+ kb->data = MEM_malloc_arrayN(mesh_dst->key->elemsize, mesh_dst->totvert, "kb->data");
+ kb->totelem = totvert;
+
+ fp = kb->data;
+ mvert = mesh_src->mvert;
+
+ for (a = 0; a < kb->totelem; a++, fp += 3, mvert++) {
+ copy_v3_v3(fp, mvert->co);
+ }
+}
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index a49896617d2..87cb1afbe38 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -546,7 +546,7 @@ static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene
*/
if (ob->type == OB_MESH) {
- DerivedMesh *dm;
+ Mesh *mesh_applied;
Mesh *me = ob->data;
Key *key = me->key;
KeyBlock *kb;
@@ -556,8 +556,8 @@ static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene
return 0;
}
- dm = mesh_create_derived_for_modifier(depsgraph, scene, ob, md, 0);
- if (!dm) {
+ mesh_applied = BKE_mesh_create_derived_for_modifier(depsgraph, scene, ob, md, 0);
+ if (!mesh_applied) {
BKE_report(reports, RPT_ERROR, "Modifier is disabled or returned error, skipping apply");
return 0;
}
@@ -572,9 +572,9 @@ static int modifier_apply_shape(ReportList *reports, Depsgraph *depsgraph, Scene
}
kb = BKE_keyblock_add(key, md->name);
- DM_to_meshkey(dm, me, kb);
+ BKE_nomain_mesh_to_meshkey(mesh_applied, me, kb);
- dm->release(dm);
+ BKE_id_free(NULL, mesh_applied);
}
else {
BKE_report(reports, RPT_ERROR, "Cannot apply modifier for this object type");
@@ -595,7 +595,7 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen
}
if (ob->type == OB_MESH) {
- DerivedMesh *dm;
+ Mesh *mesh_applied;
Mesh *me = ob->data;
MultiresModifierData *mmd = find_multires_modifier_before(scene, md);
@@ -615,13 +615,13 @@ static int modifier_apply_obdata(ReportList *reports, Depsgraph *depsgraph, Scen
}
}
else {
- dm = mesh_create_derived_for_modifier(depsgraph, scene, ob, md, 1);
- if (!dm) {
+ mesh_applied = BKE_mesh_create_derived_for_modifier(depsgraph, scene, ob, md, 1);
+ if (!mesh_applied) {
BKE_report(reports, RPT_ERROR, "Modifier returned error, skipping apply");
return 0;
}
- DM_to_mesh(dm, me, ob, CD_MASK_MESH, true);
+ BKE_nomain_mesh_to_mesh(mesh_applied, me, ob, CD_MASK_MESH, true);
if (md->type == eModifierType_Multires)
multires_customdata_delete(me);