[Bf-blender-cvs] [0faee07] alembic: New cache modifier type for creating force fields on duplis of the cached group itself.

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


Commit: 0faee07971f365150825abdf91797d5ef3f41e32
Author: Lukas Tönne
Date:   Thu Apr 16 21:16:49 2015 +0200
Branches: alembic
https://developer.blender.org/rB0faee07971f365150825abdf91797d5ef3f41e32

New cache modifier type for creating force fields on duplis of the
cached group itself.

This allows using the dupli group objects themselves as force fields,
in particular for collision objects in strand simulation. Without this
feature only the original objects of are recognized by the effectors
system, and even if duplis worked properly their settings would not be
accessible due to linking and dupli group hiding. The cache modifier
circumvents this issue by providing a new force field system, separate
from the current effectors.

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

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
M	source/blender/physics/BPH_mass_spring.h
M	source/blender/physics/intern/BPH_mass_spring.cpp

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

diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 59d1211..847b034 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -474,6 +474,10 @@ 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')
+
 
 class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
     bl_label = "Relations Extras"
diff --git a/source/blender/blenkernel/BKE_cache_library.h b/source/blender/blenkernel/BKE_cache_library.h
index dd9dd64..794f150 100644
--- a/source/blender/blenkernel/BKE_cache_library.h
+++ b/source/blender/blenkernel/BKE_cache_library.h
@@ -37,6 +37,7 @@
 struct ListBase;
 struct Main;
 struct bContext;
+struct DerivedMesh;
 struct Group;
 struct Object;
 struct Scene;
@@ -47,6 +48,7 @@ struct DupliObjectData;
 struct CacheModifier;
 struct ID;
 struct CacheProcessData;
+struct BVHTreeFromMesh;
 
 struct ClothModifierData;
 
@@ -167,4 +169,38 @@ struct CacheModifier *BKE_cache_modifier_copy(struct CacheLibrary *cachelib, str
 
 void BKE_cache_modifier_foreachIDLink(struct CacheLibrary *cachelib, struct CacheModifier *md, CacheModifier_IDWalkFunc walk, void *userdata);
 
+typedef struct CacheEffectorInstance {
+	struct CacheEffectorInstance *next, *prev;
+	
+	float mat[4][4];
+	// TODO add linear/angular velocity if necessary
+} CacheEffectorInstance;
+
+typedef struct CacheEffector {
+	int type;
+	
+	ListBase instances;
+	
+	struct DerivedMesh *dm;
+	struct BVHTreeFromMesh *treedata;
+	
+	float strength;
+} CacheEffector;
+
+typedef enum eCacheEffector_Type {
+	eCacheEffector_Type_Deflect           = 0,
+} eCacheEffector_Type;
+
+typedef struct CacheEffectorPoint {
+	float x[3], v[3];
+} CacheEffectorPoint;
+
+typedef struct CacheEffectorResult {
+	float f[3];
+} 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);
+int BKE_cache_effectors_eval(struct CacheEffector *effectors, int tot, struct CacheEffectorPoint *point, struct CacheEffectorResult *result);
+
 #endif
diff --git a/source/blender/blenkernel/intern/cache_library.c b/source/blender/blenkernel/intern/cache_library.c
index bb9cb5d..58abc16 100644
--- a/source/blender/blenkernel/intern/cache_library.c
+++ b/source/blender/blenkernel/intern/cache_library.c
@@ -43,12 +43,15 @@
 #include "DNA_cache_library_types.h"
 #include "DNA_group_types.h"
 #include "DNA_modifier_types.h"
+#include "DNA_object_force.h"
 #include "DNA_object_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_scene_types.h"
 
 #include "BKE_anim.h"
+#include "BKE_bvhutils.h"
 #include "BKE_cache_library.h"
+#include "BKE_cdderivedmesh.h"
 #include "BKE_colortools.h"
 #include "BKE_context.h"
 #include "BKE_depsgraph.h"
@@ -620,6 +623,160 @@ void BKE_cache_process_dupli_cache(CacheLibrary *cachelib, CacheProcessData *dat
 
 /* ------------------------------------------------------------------------- */
 
+static void effector_set_mesh(CacheEffector *eff, Object *ob, DerivedMesh *dm, bool create_dm, bool create_bvhtree, bool world_space)
+{
+	if (create_dm && dm) {
+		unsigned int numverts, i;
+		MVert *mvert, *mv;
+		
+		eff->dm = CDDM_copy(dm);
+		if (!eff->dm)
+			return;
+		
+		DM_ensure_tessface(eff->dm);
+		CDDM_calc_normals(eff->dm);
+		
+		numverts = eff->dm->getNumVerts(eff->dm);
+		mvert = eff->dm->getVertArray(eff->dm);
+		
+		if (world_space) {
+			/* convert to world coordinates */
+			for (i = 0, mv = mvert; i < numverts; ++i, ++mv) {
+				mul_m4_v3(ob->obmat, mv->co);
+			}
+		}
+		
+		if (create_bvhtree) {
+			if (eff->treedata)
+				free_bvhtree_from_mesh(eff->treedata);
+			else
+				eff->treedata = MEM_callocN(sizeof(BVHTreeFromMesh), "cache effector bvhtree data");
+			
+			bvhtree_from_mesh_faces(eff->treedata, eff->dm, 0.0, 2, 6);
+		}
+	}
+}
+
+static void effector_set_instances(CacheEffector *eff, Object *ob, float obmat[4][4], ListBase *duplilist)
+{
+	DupliObject *dob;
+	
+	for (dob = duplilist->first; dob; dob = dob->next) {
+		CacheEffectorInstance *inst;
+		
+		if (dob->ob != ob)
+			continue;
+		
+		inst = MEM_callocN(sizeof(CacheEffectorInstance), "cache effector instance");
+		mul_m4_m4m4(inst->mat, obmat, dob->mat);
+		
+		BLI_addtail(&eff->instances, inst);
+	}
+}
+
+static bool forcefield_get_effector(DupliCache *dupcache, float obmat[4][4], ForceFieldCacheModifier *ffmd, CacheEffector *eff)
+{
+	DupliObjectData *dobdata;
+	
+	if (!ffmd->object)
+		return false;
+	
+	dobdata = BKE_dupli_cache_find_data(dupcache, ffmd->object);
+	if (!dobdata)
+		return false;
+	
+	effector_set_mesh(eff, dobdata->ob, dobdata->dm, true, true, true);
+	effector_set_instances(eff, dobdata->ob, obmat, &dupcache->duplilist);
+	
+	eff->type = eCacheEffector_Type_Deflect;
+	eff->strength = 1000.0f;
+	
+	return true;
+}
+
+int BKE_cache_effectors_get(CacheEffector *effectors, int max, CacheLibrary *cachelib, DupliCache *dupcache, float obmat[4][4])
+{
+	CacheModifier *md;
+	int tot = 0;
+	
+	if (tot >= max)
+		return tot;
+	
+	memset(effectors, 0, sizeof(CacheEffector) * max);
+	
+	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]))
+					tot++;
+				break;
+		}
+		
+		BLI_assert(tot <= max);
+		if (tot == max)
+			break;
+	}
+	
+	return tot;
+}
+
+void BKE_cache_effectors_free(CacheEffector *effectors, int tot)
+{
+	CacheEffector *eff;
+	int i;
+	
+	for (i = 0, eff = effectors; i < tot; ++i, ++eff) {
+		BLI_freelistN(&eff->instances);
+		
+		if (eff->treedata) {
+			free_bvhtree_from_mesh(eff->treedata);
+			MEM_freeN(eff->treedata);
+		}
+		
+		if (eff->dm) {
+			eff->dm->release(eff->dm);
+		}
+	}
+}
+
+static bool cache_effector_deflect(CacheEffector *eff, CacheEffectorInstance *inst, CacheEffectorPoint *point, CacheEffectorResult *result)
+{
+	float vec[3], dist;
+	
+	sub_v3_v3v3(vec, point->x, inst->mat[3]);
+	dist = normalize_v3(vec);
+	
+	mul_v3_v3fl(result->f, vec, eff->strength);
+	
+	return true;
+}
+
+int BKE_cache_effectors_eval(CacheEffector *effectors, int tot, CacheEffectorPoint *point, CacheEffectorResult *result)
+{
+	CacheEffector *eff;
+	int i, applied = 0;
+	
+	zero_v3(result->f);
+	
+	for (i = 0, eff = effectors; i < tot; ++i, ++eff) {
+		const eCacheEffector_Type type = eff->type;
+		CacheEffectorInstance *inst;
+		
+		for (inst = eff->instances.first; inst; inst = inst->next) {
+			switch (type) {
+				case eCacheEffector_Type_Deflect:
+					if (cache_effector_deflect(eff, inst, point, result))
+						++applied;
+					break;
+			}
+		}
+	}
+	
+	return applied;
+}
+
+/* ------------------------------------------------------------------------- */
+
 static void hairsim_params_init(HairSimParams *params)
 {
 	params->timescale = 1.0f;
@@ -709,10 +866,14 @@ static bool hairsim_find_data(HairSimCacheModifier *hsmd, DupliCache *dupcache,
 
 static void hairsim_process(HairSimCacheModifier *hsmd, CacheProcessContext *ctx, CacheProcessData *data, int frame, int frame_prev, eCacheLibrary_EvalMode eval_mode)
 {
+	static const int MAX_CACHE_EFFECTORS = 64;
+	
 	Object *ob;
 	Strands *strands;
 	float mat[4][4];
 	ListBase *effectors;
+	CacheEffector cache_effectors[MAX_CACHE_EFFECTORS];
+	int tot_cache_effectors;
 	struct Implicit_Data *solver_data;
 	
 	/* only perform hair sim once */
@@ -737,10 +898,12 @@ static void hairsim_process(HairSimCacheModifier *hsmd, CacheProcessContext *ctx
 	BKE_strands_add_motion_state(strands);
 	solver_data = BPH_strands_solver_create(strands, &hsmd->sim_params);
 	effectors = pdInitEffectors(ctx->scene, ob, NULL, hsmd->sim_params.effector_weights, true);
+	tot_cache_effectors = BKE_cache_effectors_get(cache_effectors, MAX_CACHE_EFFECTORS, ctx->cachelib, data->dupcache, data->mat);
 	
-	BPH_strands_solve(strands, mat, solver_data, &hsmd->sim_params, (float)frame, (float)frame_prev, ctx->scene, effectors);
+	BPH_strands_solve(strands, mat, solver_data, &hsmd->sim_params, (float)frame, (float)frame_prev, ctx->scene, effectors, cache_effectors, tot_cache_effectors);
 	
 	pdEndEffectors(&effectors);
+	BKE_cache_effectors_free(cache_effectors, tot_cache_effectors);
 	BPH_mass_spring_solver_free(solver_data);
 }
 
@@ -756,7 +919,38 @@ CacheModifierTypeInfo cacheModifierType_HairSimulation = {
     /* free */              (CacheModifier_FreeFunc)hairsim_free,
 };
 
+static void forcefield_init(ForceFieldCacheModifier *ffmd)
+{
+	ffmd->object = NULL;
+}
+
+static void forcefield_copy(ForceFieldCacheModifier *UNUSED(ffmd), ForceFieldCacheModifier *UNUSED(tffmd))
+{
+}
+
+static void forcefield_free(ForceFieldCacheModifier *UNUSED(ffmd))
+{
+}
+
+static void forcefield_foreach_id_link(ForceFieldCacheModifier *ffmd, CacheLibrary *cachelib, CacheModifier_IDWalkFunc walk, void *userdata)
+{
+	walk(userdata, cachelib, &ffmd->modifier, (ID **)(&ffmd->object));
+}
+
+CacheModifierTypeInfo cacheModifierType_ForceField = {
+    /* name */              "ForceField",
+    /* structName */        "ForceFieldCacheModifier",
+    /* structSize */        sizeof(ForceFieldCacheModifier),
+
+    /* copy */              (CacheModifier_CopyFunc)forcefield_copy,
+    /* foreachIDLink */     (CacheModifier_ForeachIDLinkFunc)forcefield_foreach_id_link,
+    /* process */           (CacheModifier_ProcessFunc)NULL,
+    /* init */              (CacheModifier_InitFunc)forcefield_init,
+    /* free */              (CacheModifier_FreeFunc)forcefield_free,
+};
+
 void BKE_cache_modifier_init(void)
 {
 	cache_modifier_type_set(eCacheModifierType_HairSimulation, &cacheModifierType_HairSimulation);
+	cache_modifier_type_set(eCacheModifierType_ForceField, &cacheModifierType_ForceField);
 }
diff --git a/source/blender/makesdna/DNA_cache_library_types.h b/

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list