[c0dd355926a] blender2.8: Modifiers: ported applying modifier from DerivedMesh → Mesh

Sybren A. Stüvel noreply at git.blender.org
Fri Jun 1 17:53:07 CEST 2018


Commit: c0dd355926abd214570add8054e43a51af4e5b28
Author: Sybren A. Stüvel
Date:   Fri Jun 1 17:05:21 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBc0dd355926abd214570add8054e43a51af4e5b28

Modifiers: ported applying modifier from DerivedMesh → Mesh

===================================================================

M	source/blender/blenkernel/BKE_mesh.h
M	source/blender/blenkernel/intern/mesh_convert.c
M	source/blender/editors/object/object_modifier.c

===================================================================

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,
+		   

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list