[Bf-blender-cvs] [e229f43] alembic: "Deflector" force modifier for cache simulation.

Lukas Tönne noreply at git.blender.org
Fri Apr 17 09:51:09 CEST 2015


Commit: e229f431ed6f8424736d1716bc9c8bd1b9ce23eb
Author: Lukas Tönne
Date:   Fri Apr 17 09:47:58 2015 +0200
Branches: alembic
https://developer.blender.org/rBe229f431ed6f8424736d1716bc9c8bd1b9ce23eb

"Deflector" force modifier for cache simulation.

This works like the existing effectors when using "surface" mode: It
selects the closest point on the mesh surface and creates a force based
on distance and falloff.

Unlike the old effectors it also supports signed distance, based on
the surface normal, which gives more control over the allowable distance
of strands to the 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/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 847b034..5a3d0b9 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -475,8 +475,16 @@ class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
         effector_weights_ui(self, context, params.effector_weights, 'HAIR')
 
     def FORCE_FIELD(self, context, layout, cachelib, md):
-        col = layout.column()
-        col.prop_search(md, "object", context.blend_data, "objects", icon='OBJECT_DATA')
+        layout.prop_search(md, "object", context.blend_data, "objects", icon='OBJECT_DATA')
+
+        layout.prop(md, "strength")
+        layout.prop(md, "falloff")
+
+        row = layout.row()
+        row.prop(md, "min_distance")
+        row.prop(md, "max_distance")
+        
+        layout.prop(md, "use_double_sided")
 
 
 class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
diff --git a/source/blender/blenkernel/BKE_cache_library.h b/source/blender/blenkernel/BKE_cache_library.h
index 794f150..9edd8aa 100644
--- a/source/blender/blenkernel/BKE_cache_library.h
+++ b/source/blender/blenkernel/BKE_cache_library.h
@@ -173,6 +173,7 @@ typedef struct CacheEffectorInstance {
 	struct CacheEffectorInstance *next, *prev;
 	
 	float mat[4][4];
+	float imat[4][4];
 	// TODO add linear/angular velocity if necessary
 } CacheEffectorInstance;
 
@@ -184,7 +185,9 @@ typedef struct CacheEffector {
 	struct DerivedMesh *dm;
 	struct BVHTreeFromMesh *treedata;
 	
-	float strength;
+	float strength, falloff;
+	float mindist, maxdist;
+	bool double_sided;
 } CacheEffector;
 
 typedef enum eCacheEffector_Type {
diff --git a/source/blender/blenkernel/intern/cache_library.c b/source/blender/blenkernel/intern/cache_library.c
index 58abc16..aa0fc1f 100644
--- a/source/blender/blenkernel/intern/cache_library.c
+++ b/source/blender/blenkernel/intern/cache_library.c
@@ -669,6 +669,7 @@ static void effector_set_instances(CacheEffector *eff, Object *ob, float obmat[4
 		
 		inst = MEM_callocN(sizeof(CacheEffectorInstance), "cache effector instance");
 		mul_m4_m4m4(inst->mat, obmat, dob->mat);
+		invert_m4_m4(inst->imat, inst->mat);
 		
 		BLI_addtail(&eff->instances, inst);
 	}
@@ -685,11 +686,15 @@ static bool forcefield_get_effector(DupliCache *dupcache, float obmat[4][4], For
 	if (!dobdata)
 		return false;
 	
-	effector_set_mesh(eff, dobdata->ob, dobdata->dm, true, true, true);
+	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;
-	eff->strength = 1000.0f;
+	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;
 	
 	return true;
 }
@@ -739,14 +744,62 @@ void BKE_cache_effectors_free(CacheEffector *effectors, int tot)
 	}
 }
 
+static float cache_effector_falloff(const CacheEffector *eff, float distance)
+{
+	float mindist = eff->mindist;
+	float maxdist = eff->maxdist;
+	float falloff = eff->falloff;
+	float range = maxdist - mindist;
+	
+	if (range <= 0.0f)
+		return 0.0f;
+	
+	CLAMP_MIN(distance, eff->mindist);
+	CLAMP_MAX(distance, eff->maxdist);
+	CLAMP_MIN(falloff, 0.0f);
+	
+	return powf(1.0f - (distance - mindist) / range, falloff);
+}
+
 static bool cache_effector_deflect(CacheEffector *eff, CacheEffectorInstance *inst, CacheEffectorPoint *point, CacheEffectorResult *result)
 {
-	float vec[3], dist;
+	BVHTreeNearest nearest = {0, };
+	float co[3];
 	
-	sub_v3_v3v3(vec, point->x, inst->mat[3]);
-	dist = normalize_v3(vec);
+	if (!eff->treedata)
+		return false;
+	
+	nearest.dist_sq = FLT_MAX;
+	
+	/* lookup in object space */
+	mul_v3_m4v3(co, inst->imat, point->x);
+	
+	BLI_bvhtree_find_nearest(eff->treedata->tree, co, &nearest, eff->treedata->nearest_callback, eff->treedata);
+	if (nearest.index < 0)
+		return false;
 	
-	mul_v3_v3fl(result->f, vec, eff->strength);
+	/* convert back to world space */
+	mul_m4_v3(inst->mat, nearest.co);
+	
+	{
+		float vec[3], dist;
+		float factor;
+		
+		sub_v3_v3v3(vec, point->x, nearest.co);
+		
+		dist = normalize_v3(vec);
+		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)
+				dist = -dist;
+		}
+		
+		factor = cache_effector_falloff(eff, dist);
+		
+		mul_v3_v3fl(result->f, vec, eff->strength * factor);
+	}
 	
 	return true;
 }
@@ -922,6 +975,11 @@ CacheModifierTypeInfo cacheModifierType_HairSimulation = {
 static void forcefield_init(ForceFieldCacheModifier *ffmd)
 {
 	ffmd->object = NULL;
+	
+	ffmd->strength = 0.0f;
+	ffmd->falloff = 1.0f;
+	ffmd->min_distance = 0.0f;
+	ffmd->max_distance = 1.0f;
 }
 
 static void forcefield_copy(ForceFieldCacheModifier *UNUSED(ffmd), ForceFieldCacheModifier *UNUSED(tffmd))
diff --git a/source/blender/makesdna/DNA_cache_library_types.h b/source/blender/makesdna/DNA_cache_library_types.h
index 901a91e..e144232 100644
--- a/source/blender/makesdna/DNA_cache_library_types.h
+++ b/source/blender/makesdna/DNA_cache_library_types.h
@@ -160,6 +160,16 @@ typedef struct ForceFieldCacheModifier {
 	CacheModifier modifier;
 	
 	struct Object *object;
+	
+	int flag;
+	float strength;
+	float min_distance, max_distance;
+	float falloff;
+	int pad;
 } ForceFieldCacheModifier;
 
+typedef enum eForceFieldCacheModifier_Flag {
+	eForceFieldCacheModifier_Flag_DoubleSided           = (1 << 0),
+} eForceFieldCacheModifier_Flag;
+
 #endif
diff --git a/source/blender/makesrna/intern/rna_cache_library.c b/source/blender/makesrna/intern/rna_cache_library.c
index c4fade4..7d510ae 100644
--- a/source/blender/makesrna/intern/rna_cache_library.c
+++ b/source/blender/makesrna/intern/rna_cache_library.c
@@ -378,6 +378,35 @@ static void rna_def_cache_modifier_force_field(BlenderRNA *brna)
 	RNA_def_property_flag(prop, PROP_EDITABLE);
 	RNA_def_property_ui_text(prop, "Object", "Object whose cache to simulate");
 	RNA_def_property_update(prop, 0, "rna_CacheModifier_update");
+	
+	prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+	RNA_def_property_ui_range(prop, -10000.0f, 10000.0f, 0.1, 3);
+	RNA_def_property_ui_text(prop, "Strength", "");
+	RNA_def_property_update(prop, 0, "rna_CacheModifier_update");
+	
+	prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_range(prop, 0.0f, FLT_MAX);
+	RNA_def_property_ui_range(prop, 0.0f, 10.0f, 0.1, 3);
+	RNA_def_property_ui_text(prop, "Falloff", "");
+	RNA_def_property_update(prop, 0, "rna_CacheModifier_update");
+	
+	prop = RNA_def_property(srna, "min_distance", PROP_FLOAT, PROP_DISTANCE);
+	RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+	RNA_def_property_ui_range(prop, -100.0f, 100.0f, 0.1, 4);
+	RNA_def_property_ui_text(prop, "Minimum Distance", "");
+	RNA_def_property_update(prop, 0, "rna_CacheModifier_update");
+	
+	prop = RNA_def_property(srna, "max_distance", PROP_FLOAT, PROP_DISTANCE);
+	RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
+	RNA_def_property_ui_range(prop, -100.0f, 100.0f, 0.1, 4);
+	RNA_def_property_ui_text(prop, "Maximum Distance", "");
+	RNA_def_property_update(prop, 0, "rna_CacheModifier_update");
+	
+	prop = RNA_def_property(srna, "use_double_sided", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flag", eForceFieldCacheModifier_Flag_DoubleSided);
+	RNA_def_property_ui_text(prop, "Use Double Sided", "");
+	RNA_def_property_update(prop, 0, "rna_CacheModifier_update");
 }
 
 static void rna_def_cache_modifier(BlenderRNA *brna)




More information about the Bf-blender-cvs mailing list