[Bf-blender-cvs] [d5228eb] alembic: Drag type force field for keeping hairs "stuck" to a mesh surface.

Lukas Tönne noreply at git.blender.org
Mon May 11 11:40:40 CEST 2015


Commit: d5228eb9922d6a180ac20b130091f3fc090c2d6e
Author: Lukas Tönne
Date:   Sun May 10 14:04:05 2015 +0200
Branches: alembic
https://developer.blender.org/rBd5228eb9922d6a180ac20b130091f3fc090c2d6e

Drag type force field for keeping hairs "stuck" to a mesh surface.

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

M	release/scripts/startup/bl_ui/properties_object.py
M	source/blender/blenkernel/BKE_cache_library.h
M	source/blender/blenkernel/intern/cache_library.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/makesdna/DNA_cache_library_types.h
M	source/blender/makesrna/intern/rna_cache_library.c

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

diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 28fd129..fbcde95 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -543,14 +543,17 @@ class OBJECT_PT_cache_library(ObjectButtonsPanel, Panel):
     def FORCE_FIELD(self, context, layout, cachelib, md):
         layout.prop_search(md, "object", context.blend_data, "objects", icon='OBJECT_DATA')
 
-        layout.prop(md, "strength")
-        layout.prop(md, "falloff")
+        layout.prop(md, "force_type", text="")
 
-        row = layout.row()
+        row = layout.row(align=True)
+        row.prop(md, "strength")
+        row.prop(md, "falloff")
+
+        col = layout.column(align=True)
+        row = layout.row(align=True)
         row.prop(md, "min_distance")
         row.prop(md, "max_distance")
-        
-        layout.prop(md, "use_double_sided")
+        col.prop(md, "use_double_sided")
 
     def SHRINK_WRAP(self, context, layout, cachelib, md):
         col = layout.column(align=True)
diff --git a/source/blender/blenkernel/BKE_cache_library.h b/source/blender/blenkernel/BKE_cache_library.h
index 4258ac7..508353c 100644
--- a/source/blender/blenkernel/BKE_cache_library.h
+++ b/source/blender/blenkernel/BKE_cache_library.h
@@ -202,6 +202,7 @@ typedef struct CacheEffector {
 	
 	struct DerivedMesh *dm;
 	struct BVHTreeFromMesh *treedata;
+	struct ForceFieldVertexCache *vertex_cache;
 	
 	float strength, falloff;
 	float mindist, maxdist;
@@ -210,6 +211,7 @@ typedef struct CacheEffector {
 
 typedef enum eCacheEffector_Type {
 	eCacheEffector_Type_Deflect           = 0,
+	eCacheEffector_Type_Drag              = 1,
 } eCacheEffector_Type;
 
 typedef struct CacheEffectorPoint {
@@ -223,6 +225,7 @@ typedef struct CacheEffectorResult {
 
 int BKE_cache_effectors_get(struct CacheEffector *effectors, int max, struct CacheLibrary *cachelib, struct DupliCache *dupcache, float obmat[4][4]);
 void BKE_cache_effectors_free(struct CacheEffector *effectors, int tot);
+void BKE_cache_effector_velocity_update(struct CacheLibrary *cachelib, struct DupliCache *dupcache, float obmat[4][4], float frame);
 int BKE_cache_effectors_eval(struct CacheEffector *effectors, int tot, struct CacheEffectorPoint *point, struct CacheEffectorResult *result);
 
 /* ========================================================================= */
diff --git a/source/blender/blenkernel/intern/cache_library.c b/source/blender/blenkernel/intern/cache_library.c
index 6b24919..54a0965 100644
--- a/source/blender/blenkernel/intern/cache_library.c
+++ b/source/blender/blenkernel/intern/cache_library.c
@@ -593,6 +593,11 @@ void BKE_cache_process_dupli_cache(CacheLibrary *cachelib, CacheProcessData *dat
 
 /* ------------------------------------------------------------------------- */
 
+static ForceFieldVertexCache *forcefield_vertex_cache_new(void);
+static void forcefield_vertex_cache_free(ForceFieldVertexCache *cache);
+static void forcefield_vertex_cache_clear(ForceFieldVertexCache *cache);
+static void forcefield_vertex_cache_init(ForceFieldVertexCache *cache, float frame, DerivedMesh *dm);
+
 static void effector_set_mesh(CacheEffector *eff, Object *ob, DerivedMesh *dm, bool create_dm, bool create_bvhtree, bool world_space)
 {
 	if (create_dm && dm) {
@@ -659,12 +664,21 @@ static bool forcefield_get_effector(DupliCache *dupcache, float obmat[4][4], For
 	effector_set_mesh(eff, dobdata->ob, dobdata->dm, true, true, false);
 	effector_set_instances(eff, dobdata->ob, obmat, &dupcache->duplilist);
 	
-	eff->type = eCacheEffector_Type_Deflect;
+	switch (ffmd->type) {
+		case eForceFieldCacheModifier_Type_Deflect:
+			eff->type = eCacheEffector_Type_Deflect;
+			break;
+		case eForceFieldCacheModifier_Type_Drag:
+			eff->type = eCacheEffector_Type_Drag;
+			break;
+	}
+	
 	eff->strength = ffmd->strength;
 	eff->falloff = ffmd->falloff;
 	eff->mindist = ffmd->min_distance;
 	eff->maxdist = ffmd->max_distance;
 	eff->double_sided = ffmd->flag & eForceFieldCacheModifier_Flag_DoubleSided;
+	eff->vertex_cache = ffmd->vertex_cache;
 	
 	return true;
 }
@@ -681,10 +695,12 @@ int BKE_cache_effectors_get(CacheEffector *effectors, int max, CacheLibrary *cac
 	
 	for (md = cachelib->modifiers.first; md; md = md->next) {
 		switch (md->type) {
-			case eCacheModifierType_ForceField:
-				if (forcefield_get_effector(dupcache, obmat, (ForceFieldCacheModifier *)md, &effectors[tot]))
+			case eCacheModifierType_ForceField: {
+				ForceFieldCacheModifier *ffmd = (ForceFieldCacheModifier *)md;
+				if (forcefield_get_effector(dupcache, obmat, ffmd, &effectors[tot]))
 					tot++;
 				break;
+			}
 		}
 		
 		BLI_assert(tot <= max);
@@ -714,6 +730,58 @@ void BKE_cache_effectors_free(CacheEffector *effectors, int tot)
 	}
 }
 
+static bool forcefield_velocity_update(DupliCache *dupcache, float obmat[4][4], float frame, ForceFieldCacheModifier *ffmd)
+{
+	DupliObjectData *dobdata;
+	bool use_vertex_cache = false;
+	
+	if (!ffmd->object)
+		return false;
+	
+	dobdata = BKE_dupli_cache_find_data(dupcache, ffmd->object);
+	if (!dobdata)
+		return false;
+	
+	switch (ffmd->type) {
+		case eForceFieldCacheModifier_Type_Drag:
+			use_vertex_cache = true;
+			break;
+	}
+	
+	if (use_vertex_cache) {
+		if (!ffmd->vertex_cache) {
+			ffmd->vertex_cache = forcefield_vertex_cache_new();
+		}
+		
+		forcefield_vertex_cache_init(ffmd->vertex_cache, frame, dobdata->dm);
+		{
+			int i;
+			for (i = 0; i < ffmd->vertex_cache->totvert; ++i) {
+				float x[3], v[3];
+				mul_v3_m4v3(x, obmat, ffmd->vertex_cache->co_prev[i]);
+				copy_v3_v3(v, ffmd->vertex_cache->vel[i]);
+				mul_mat3_m4_v3(obmat, v);
+				BKE_sim_debug_data_add_vector(x, v, 1,1,0, "hairsim", 45232, i);
+			}
+		}
+	}
+	
+	return true;
+}
+
+void BKE_cache_effector_velocity_update(CacheLibrary *cachelib, DupliCache *dupcache, float obmat[4][4], float frame)
+{
+	CacheModifier *md;
+	
+	for (md = cachelib->modifiers.first; md; md = md->next) {
+		switch (md->type) {
+			case eCacheModifierType_ForceField:
+				forcefield_velocity_update(dupcache, obmat, frame, (ForceFieldCacheModifier *)md);
+				break;
+		}
+	}
+}
+
 static float cache_effector_falloff(const CacheEffector *eff, float distance)
 {
 	float mindist = eff->mindist;
@@ -731,10 +799,42 @@ static float cache_effector_falloff(const CacheEffector *eff, float distance)
 	return powf(1.0f - (distance - mindist) / range, falloff);
 }
 
-static bool cache_effector_deflect(CacheEffector *eff, CacheEffectorInstance *inst, CacheEffectorPoint *point, CacheEffectorResult *result)
+typedef struct CacheEffectorTessfaceData {
+	int face_index;
+	MFace *mface;
+	MVert *mvert[4];
+	float weight[4];
+} CacheEffectorTessfaceData;
+
+static void cache_effector_velocity(const CacheEffector *eff, CacheEffectorInstance *inst, CacheEffectorTessfaceData *tessface, float vel[3])
 {
+	zero_v3(vel);
+	
+	if (!eff->vertex_cache)
+		return;
+	
+	BLI_assert(eff->vertex_cache->totvert == eff->dm->getNumVerts(eff->dm));
+	
+	madd_v3_v3fl(vel, eff->vertex_cache->vel[tessface->mface->v1], tessface->weight[0]);
+	madd_v3_v3fl(vel, eff->vertex_cache->vel[tessface->mface->v2], tessface->weight[1]);
+	madd_v3_v3fl(vel, eff->vertex_cache->vel[tessface->mface->v3], tessface->weight[2]);
+	if (tessface->mface->v4)
+		madd_v3_v3fl(vel, eff->vertex_cache->vel[tessface->mface->v4], tessface->weight[3]);
+	
+	/* vertex cache velocities are in local space, effector results are all expected in world space */
+	mul_mat3_m4_v3(inst->mat, vel);
+}
+
+static bool cache_effector_find_nearest(CacheEffector *eff, CacheEffectorInstance *inst, CacheEffectorPoint *point,
+                                        float r_vec[3], float r_nor[3], float *r_dist, bool *r_inside,
+                                        CacheEffectorTessfaceData *r_tessface)
+{
+	const bool need_inside = r_dist || r_inside;
+	
 	BVHTreeNearest nearest = {0, };
-	float co[3];
+	float world_near_co[3], world_near_no[3];
+	float co[3], vec[3], dist;
+	bool inside;
 	
 	if (!eff->treedata)
 		return false;
@@ -749,36 +849,88 @@ static bool cache_effector_deflect(CacheEffector *eff, CacheEffectorInstance *in
 		return false;
 	
 	/* convert back to world space */
-	mul_m4_v3(inst->mat, nearest.co);
+	mul_v3_m4v3(world_near_co, inst->mat, nearest.co);
+	copy_v3_v3(world_near_no, nearest.no);
+	mul_mat3_m4_v3(inst->mat, world_near_no);
 	
-	{
-		float vec[3], dist;
-		bool inside = false;
-		float factor;
-		
-		sub_v3_v3v3(vec, point->x, nearest.co);
-		
-		dist = normalize_v3(vec);
+	sub_v3_v3v3(vec, point->x, world_near_co);
+	dist = normalize_v3(vec);
+	
+	if (need_inside) {
+		inside = false;
 		if (!eff->double_sided) {
-			/* dm normal also needed in world space */
-			mul_mat3_m4_v3(inst->mat, nearest.no);
-			
-			if (dot_v3v3(vec, nearest.no) < 0.0f) {
+			if (dot_v3v3(vec, world_near_no) < 0.0f) {
 				dist = -dist;
 				inside = true;
 			}
 		}
+	}
+	
+	if (r_vec) copy_v3_v3(r_vec, vec);
+	if (r_nor) copy_v3_v3(r_nor, world_near_no);
+	if (r_dist) *r_dist = dist;
+	if (r_inside) *r_inside = inside;
+	
+	if (r_tessface && eff->dm) {
+		CacheEffectorTessfaceData *t = r_tessface;
+		DerivedMesh *dm = eff->dm;
+		MFace *mf = dm->getTessFaceArray(dm) + nearest.index;
+		MVert *mverts = dm->getVertArray(dm);
 		
-		factor = cache_effector_falloff(eff, dist);
+		t->face_index = nearest.index;
+		t->mface = mf;
+		t->mvert[0] = &mverts[mf->v1];
+		t->mvert[1] = &mverts[mf->v2];
+		t->mvert[2] = &mverts[mf->v3];
 		
-		mul_v3_v3fl(result->f, vec, eff->strength * factor);
-		if (inside)
-			negate_v3(result->f);
+		if (mf->v4) {
+			t->mvert[3] = &mverts[mf->v4];
+			interp_weights_face_v3(t->weight, t->mvert[0]->co, t->mvert[1]->co, t->mvert[2]->co, t->mvert[3]->co, nearest.co);
+		}
+		else {
+			t->mvert[3] = NULL;
+			interp_weights_face_v3(t->weight, t->mvert[0]->co, t->mvert[1]->co, t->mvert[2]->co, NULL, nearest.co);
+		}
 	}
 	
 	return true;
 }
 
+static bool cache_effector_deflect(CacheEffector *eff, CacheEffectorInstance *inst, CacheEffectorPoint *point, CacheEffectorResult *result)
+{
+	float vec[3], dist, falloff;
+	bool inside;
+	
+	if (!cache_effector_find_nearest(eff,

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list