[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25487] trunk/blender: Solidify modifier for Durian ( allow cloth sim on single layer and make solid after)

Campbell Barton ideasman42 at gmail.com
Mon Dec 21 02:02:09 CET 2009


Revision: 25487
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25487
Author:   campbellbarton
Date:     2009-12-21 02:02:08 +0100 (Mon, 21 Dec 2009)

Log Message:
-----------
Solidify modifier for Durian (allow cloth sim on single layer and make solid after)
Mostly the same as the recently added editmode tool with some extras.

* Options to disable filling in the rim between inner and outer surface, since its faster not to detect this in cases where its not needed.
* Option to disable high quality normal calculation, mostly noticable when operating on building walls, not needed for cloth or more organic shapes.
* Option to disable 'even thickness', again, not needed in some cases.

Also options for creasing inner/outer and rim edges, need this for makign Sintels cloths solid since zero crease looks far too soft.

note:
* UVs and VCols etc are copied to the new skin however rim faces dont get the UVs or vcols set from the faces they are created from yet.
* Normals are assumed to be pointing outwards
* used patch from Uncle Entity as a template since it added the DNA and RNA entries but the actual modifier from the patch wasnt used.

Modified Paths:
--------------
    trunk/blender/release/scripts/ui/properties_data_modifier.py
    trunk/blender/source/blender/blenkernel/intern/modifier.c
    trunk/blender/source/blender/editors/mesh/editmesh_lib.c
    trunk/blender/source/blender/makesdna/DNA_meshdata_types.h
    trunk/blender/source/blender/makesdna/DNA_modifier_types.h
    trunk/blender/source/blender/makesrna/RNA_access.h
    trunk/blender/source/blender/makesrna/intern/rna_modifier.c

Modified: trunk/blender/release/scripts/ui/properties_data_modifier.py
===================================================================
--- trunk/blender/release/scripts/ui/properties_data_modifier.py	2009-12-20 23:34:05 UTC (rev 25486)
+++ trunk/blender/release/scripts/ui/properties_data_modifier.py	2009-12-21 01:02:08 UTC (rev 25487)
@@ -600,6 +600,20 @@
     def SOFT_BODY(self, layout, ob, md, wide_ui):
         layout.label(text="See Soft Body panel.")
 
+    def SOLIDIFY(self, layout, ob, md, wide_ui):
+        split = layout.split()
+
+        col = split.column()
+        col.prop(md, "offset")
+        col.prop(md, "use_rim")
+        col.prop(md, "use_even_offset")
+        col.prop(md, "use_quality_normals")
+        col.prop(md, "edge_crease_inner")
+        col.prop(md, "edge_crease_outer")
+        col.prop(md, "edge_crease_rim")
+        # col.label(text="Vertex Group:")
+        # col.prop_object(md, "vertex_group", ob, "vertex_groups", text="")
+
     def SUBSURF(self, layout, ob, md, wide_ui):
         if wide_ui:
             layout.row().prop(md, "subdivision_type", expand=True)

Modified: trunk/blender/source/blender/blenkernel/intern/modifier.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/modifier.c	2009-12-20 23:34:05 UTC (rev 25486)
+++ trunk/blender/source/blender/blenkernel/intern/modifier.c	2009-12-21 01:02:08 UTC (rev 25487)
@@ -5807,6 +5807,432 @@
 	return 1;
 }
 
+/* Solidify */
+
+
+typedef struct EdgeFaceRef {
+	int f1; /* init as -1 */
+	int f2;
+} EdgeFaceRef;
+
+static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3])
+{
+	int i, numVerts, numEdges, numFaces;
+	MFace *mface, *mf;
+	MVert *mvert, *mv;
+
+	float (*face_nors)[3];
+	float *f_no;
+	int calc_face_nors= 0;
+
+	numVerts = dm->getNumVerts(dm);
+	numEdges = dm->getNumEdges(dm);
+	numFaces = dm->getNumFaces(dm);
+	mface = dm->getFaceArray(dm);
+	mvert = dm->getVertArray(dm);
+
+	/* we don't want to overwrite any referenced layers */
+
+	/*
+	Dosnt work here!
+	mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
+	cddm->mvert = mv;
+	*/
+
+	face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
+	if(!face_nors) {
+		calc_face_nors = 1;
+		face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC, NULL, numFaces);
+	}
+
+	mv = mvert;
+	mf = mface;
+
+	{
+		EdgeHash *edge_hash = BLI_edgehash_new();
+		EdgeHashIterator *edge_iter;
+		int edge_ref_count = 0;
+		int ed_v1, ed_v2; /* use when getting the key */
+		EdgeFaceRef *edge_ref_array = MEM_callocN(numEdges * sizeof(EdgeFaceRef), "Edge Connectivity");
+		EdgeFaceRef *edge_ref;
+		float edge_normal[3];
+
+		/* This function adds an edge hash if its not there, and adds the face index */
+#define NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(EDV1, EDV2); \
+				edge_ref = (EdgeFaceRef *)BLI_edgehash_lookup(edge_hash, EDV1, EDV2); \
+				if (!edge_ref) { \
+					edge_ref = &edge_ref_array[edge_ref_count]; edge_ref_count++; \
+					edge_ref->f1=i; \
+					edge_ref->f2=-1; \
+					BLI_edgehash_insert(edge_hash, EDV1, EDV2, edge_ref); \
+				} else { \
+					edge_ref->f2=i; \
+				}
+
+		for(i = 0; i < numFaces; i++, mf++) {
+			f_no = face_nors[i];
+
+			if(mf->v4) {
+				if(calc_face_nors)
+					normal_quad_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
+
+				NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2);
+				NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3);
+				NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v4);
+				NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v4, mf->v1);
+			} else {
+				if(calc_face_nors)
+					normal_tri_v3(f_no, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
+
+				NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v1, mf->v2);
+				NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v2, mf->v3);
+				NOCALC_EDGEWEIGHT_ADD_EDGEREF_FACE(mf->v3, mf->v1);
+			}
+		}
+
+		for(edge_iter = BLI_edgehashIterator_new(edge_hash); !BLI_edgehashIterator_isDone(edge_iter); BLI_edgehashIterator_step(edge_iter)) {
+			/* Get the edge vert indicies, and edge value (the face indicies that use it)*/
+			BLI_edgehashIterator_getKey(edge_iter, (int*)&ed_v1, (int*)&ed_v2);
+			edge_ref = BLI_edgehashIterator_getValue(edge_iter);
+
+			if (edge_ref->f2 != -1) {
+				/* We have 2 faces using this edge, calculate the edges normal
+				 * using the angle between the 2 faces as a weighting */
+				add_v3_v3v3(edge_normal, face_nors[edge_ref->f1], face_nors[edge_ref->f2]);
+				normalize_v3(edge_normal);
+				mul_v3_fl(edge_normal, angle_normalized_v3v3(face_nors[edge_ref->f1], face_nors[edge_ref->f2]));
+			} else {
+				/* only one face attached to that edge */
+				/* an edge without another attached- the weight on this is
+				 * undefined, M_PI/2 is 90d in radians and that seems good enough */
+				VECCOPY(edge_normal, face_nors[edge_ref->f1])
+				mul_v3_fl(edge_normal, M_PI/2);
+			}
+			add_v3_v3(temp_nors[ed_v1], edge_normal);
+			add_v3_v3(temp_nors[ed_v2], edge_normal);
+		}
+		BLI_edgehashIterator_free(edge_iter);
+		BLI_edgehash_free(edge_hash, NULL);
+		MEM_freeN(edge_ref_array);
+	}
+
+	/* normalize vertex normals and assign */
+	for(i = 0; i < numVerts; i++, mv++) {
+		if(normalize_v3(temp_nors[i]) == 0.0f) {
+			normal_short_to_float_v3(temp_nors[i], mv->no);
+		}
+	}
+}
+ 
+static void solidifyModifier_initData(ModifierData *md)
+{
+	SolidifyModifierData *smd = (SolidifyModifierData*) md;
+	smd->offset = 0.01f;
+	smd->flag = MOD_SOLIDIFY_EVEN | MOD_SOLIDIFY_RIM | MOD_SOLIDIFY_NORMAL_CALC;
+}
+ 
+static void solidifyModifier_copyData(ModifierData *md, ModifierData *target)
+{
+	SolidifyModifierData *smd = (SolidifyModifierData*) md;
+	SolidifyModifierData *tsmd = (SolidifyModifierData*) target;
+	tsmd->offset = smd->offset;
+	tsmd->crease_inner = smd->crease_inner;
+	tsmd->crease_outer = smd->crease_outer;
+	tsmd->crease_rim = smd->crease_rim;
+	strcpy(tsmd->vgroup, smd->vgroup);
+}
+
+static DerivedMesh *solidifyModifier_applyModifier(ModifierData *md,
+						   Object *ob, 
+						   DerivedMesh *dm,
+						   int useRenderParams,
+						   int isFinalCalc)
+{
+	int i;
+	DerivedMesh *result;
+	SolidifyModifierData *smd = (SolidifyModifierData*) md;
+
+	MFace *mf, *mface, *orig_mface;
+	MEdge *ed, *medge, *orig_medge;
+	MVert *mv, *mvert, *orig_mvert;
+
+	int numVerts = dm->getNumVerts(dm);
+	int numEdges = dm->getNumEdges(dm);
+	int numFaces = dm->getNumFaces(dm);
+
+	/* use for edges */
+	int *new_vert_arr= NULL;
+	int newFaces = 0;
+
+	int *new_edge_arr= NULL;
+	int newEdges = 0;
+
+	float (*vert_nors)[3]= NULL;
+
+	orig_mface = dm->getFaceArray(dm);
+	orig_medge = dm->getEdgeArray(dm);
+	orig_mvert = dm->getVertArray(dm);
+
+	if(smd->flag & MOD_SOLIDIFY_RIM) {
+		EdgeHash *edgehash = BLI_edgehash_new();
+		EdgeHashIterator *ehi;
+		int v1, v2;
+		int *edge_users;
+
+		for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) {
+			mv->flag &= ~ME_VERT_TMP_TAG;
+		}
+
+		for(i=0, ed=orig_medge; i<numEdges; i++, ed++) {
+			BLI_edgehash_insert(edgehash, ed->v1, ed->v2, (void *)i);
+		}
+
+		edge_users= MEM_callocN(sizeof(int) * numEdges, "solid_mod edges");
+
+/* will be incorrect if an edge happens to have this many face users (very unlikely) */
+#define LARGE_NUM 1000000
+
+		for(i=0, mf=orig_mface; i<numFaces; i++, mf++) {
+			if(mf->v4) {
+				edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v1, mf->v2)] += mf->v1 < mf->v2 ? 1:LARGE_NUM;
+				edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v2, mf->v3)] += mf->v2 < mf->v3 ? 1:LARGE_NUM;
+				edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v3, mf->v4)] += mf->v3 < mf->v4 ? 1:LARGE_NUM;
+				edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v4, mf->v1)] += mf->v4 < mf->v1 ? 1:LARGE_NUM;
+			}
+			else {
+				edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v1, mf->v2)] += mf->v1 < mf->v2 ? 1:LARGE_NUM;
+				edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v2, mf->v3)] += mf->v2 < mf->v3 ? 1:LARGE_NUM;
+				edge_users[(int)BLI_edgehash_lookup(edgehash, mf->v3, mf->v1)] += mf->v3 < mf->v1 ? 1:LARGE_NUM;
+			}
+		}
+
+		new_edge_arr= MEM_callocN(sizeof(int) * numEdges, "solid_mod arr");
+
+		ehi= BLI_edgehashIterator_new(edgehash);
+		for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
+			int eidx= (int)BLI_edgehashIterator_getValue(ehi);
+			if(edge_users[eidx] == 1 || edge_users[eidx] == LARGE_NUM) {
+				BLI_edgehashIterator_getKey(ehi, &v1, &v2);
+
+				/* we need to order the edge */
+				if(edge_users[eidx] == LARGE_NUM) {
+					eidx= -(eidx + 1);
+				}
+
+				orig_mvert[v1].flag |= ME_VERT_TMP_TAG;
+				orig_mvert[v2].flag |= ME_VERT_TMP_TAG;
+				new_edge_arr[newFaces]= eidx;
+				newFaces++;
+			}
+		}
+		BLI_edgehashIterator_free(ehi);
+		MEM_freeN(edge_users);
+
+#undef LARGE_NUM
+
+		new_vert_arr= MEM_callocN(sizeof(int) * numVerts, "solid_mod new_varr");
+		for(i=0, mv=orig_mvert; i<numVerts; i++, mv++) {
+			if(mv->flag & ME_VERT_TMP_TAG) {
+				new_vert_arr[newEdges] = i;
+				newEdges++;
+
+				mv->flag &= ~ME_VERT_TMP_TAG;
+			}
+		}
+
+		BLI_edgehash_free(edgehash, NULL);
+	}
+
+	if(smd->flag & MOD_SOLIDIFY_NORMAL_CALC) {
+		vert_nors= MEM_callocN(sizeof(float) * numVerts * 3, "mod_solid_vno_hq");
+		dm_calc_normal(dm, vert_nors);
+	}
+
+	result = CDDM_from_template(dm, numVerts * 2, (numEdges * 2) + newEdges, (numFaces * 2) + newFaces);
+
+	mface = result->getFaceArray(result);
+	medge = result->getEdgeArray(result);
+	mvert = result->getVertArray(result);
+
+	DM_copy_face_data(dm, result, 0, 0, numFaces);
+	DM_copy_face_data(dm, result, 0, numFaces, numFaces);
+
+	DM_copy_edge_data(dm, result, 0, 0, numEdges);
+	DM_copy_edge_data(dm, result, 0, numEdges, numEdges);
+
+	DM_copy_vert_data(dm, result, 0, 0, numVerts);
+	DM_copy_vert_data(dm, result, 0, numVerts, numVerts);
+
+	{
+		static int corner_indices[4] = {2, 1, 0, 3};
+		int is_quad;
+
+		for(i=0, mf=mface+numFaces; i<numFaces; i++, mf++) {
+			mf->v1 += numVerts;
+			mf->v2 += numVerts;
+			mf->v3 += numVerts;
+			if(mf->v4)
+				mf->v4 += numVerts;
+
+			/* Flip face normal */
+			{
+				is_quad = mf->v4;
+				SWAP(int, mf->v1, mf->v3);
+				DM_swap_face_data(result, i+numFaces, corner_indices);
+				test_index_face(mf, &result->faceData, numFaces, is_quad ? 4:3);
+			}
+		}
+	}
+
+	for(i=0, ed=medge+numEdges; i<numEdges; i++, ed++) {
+		ed->v1 += numVerts;
+		ed->v2 += numVerts;
+	}
+
+	if((smd->flag & MOD_SOLIDIFY_EVEN) == 0) {
+		/* no even thickness, very simple */
+		float scalar_short = smd->offset / 32767.0f;
+

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list