[Bf-blender-cvs] [29ed48c] alembic: New cache modifier "Haircut", for removing unwanted child hairs.

Lukas Tönne noreply at git.blender.org
Fri May 22 17:53:29 CEST 2015


Commit: 29ed48cced3b9720a68d6d6ebae8f30ae82d1fbf
Author: Lukas Tönne
Date:   Thu May 21 19:57:21 2015 +0200
Branches: alembic
https://developer.blender.org/rB29ed48cced3b9720a68d6d6ebae8f30ae82d1fbf

New cache modifier "Haircut", for removing unwanted child hairs.

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

M	release/scripts/startup/bl_ui/properties_object.py
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 d781e0d..6241c86 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -557,6 +557,21 @@ class OBJECT_PT_cache_library(ObjectButtonsPanel, Panel):
         row.prop(md, "max_distance")
         col.prop(md, "use_double_sided")
 
+    def HAIRCUT(self, context, layout, cachelib, md):
+        col = layout.column(align=True)
+        col.prop_search(md, "object", context.blend_data, "objects", icon='OBJECT_DATA')
+        sub = col.column()
+        if (md.object):
+            sub.prop_search(md, "hair_system", md.object, "particle_systems")
+        else:
+            sub.enabled = False
+            sub.prop(md, "hair_system")
+
+        layout.prop_search(md, "target", context.blend_data, "objects", icon='OBJECT_DATA')
+
+        layout = layout.column()
+        layout.active = md.hair_system is not None
+
     def SHRINK_WRAP(self, context, layout, cachelib, md):
         col = layout.column(align=True)
         col.prop_search(md, "object", context.blend_data, "objects", icon='OBJECT_DATA')
diff --git a/source/blender/blenkernel/intern/cache_library.c b/source/blender/blenkernel/intern/cache_library.c
index 68e0a50..0878ee8 100644
--- a/source/blender/blenkernel/intern/cache_library.c
+++ b/source/blender/blenkernel/intern/cache_library.c
@@ -1655,6 +1655,191 @@ bool BKE_cache_modifier_strands_key_get(Object *ob, StrandsKeyCacheModifier **r_
 	return false;
 }
 
+/* ------------------------------------------------------------------------- */
+
+static void haircut_init(HaircutCacheModifier *hmd)
+{
+	hmd->object = NULL;
+	hmd->hair_system = -1;
+}
+
+static void haircut_copy(HaircutCacheModifier *UNUSED(hmd), HaircutCacheModifier *UNUSED(thmd))
+{
+}
+
+static void haircut_free(HaircutCacheModifier *UNUSED(hmd))
+{
+}
+
+static void haircut_foreach_id_link(HaircutCacheModifier *smd, CacheLibrary *cachelib, CacheModifier_IDWalkFunc walk, void *userdata)
+{
+	walk(userdata, cachelib, &smd->modifier, (ID **)(&smd->object));
+	walk(userdata, cachelib, &smd->modifier, (ID **)(&smd->target));
+}
+
+typedef struct HaircutCacheData {
+	DerivedMesh *dm;
+	BVHTreeFromMesh treedata;
+	
+	ListBase instances;
+} HaircutCacheData;
+
+typedef struct HaircutCacheInstance {
+	struct HaircutCacheInstance *next, *prev;
+	
+	float mat[4][4];
+	float imat[4][4];
+} HaircutCacheInstance;
+
+static void haircut_data_get_bvhtree(HaircutCacheData *data, DerivedMesh *dm, bool create_bvhtree)
+{
+	data->dm = CDDM_copy(dm);
+	if (!data->dm)
+		return;
+	
+	DM_ensure_tessface(data->dm);
+	CDDM_calc_normals(data->dm);
+	
+	if (create_bvhtree) {
+		bvhtree_from_mesh_faces(&data->treedata, data->dm, 0.0, 2, 6);
+	}
+}
+
+static void haircut_data_get_instances(HaircutCacheData *data, Object *ob, float obmat[4][4], ListBase *duplilist)
+{
+	DupliObject *dob;
+	
+	for (dob = duplilist->first; dob; dob = dob->next) {
+		HaircutCacheInstance *inst;
+		
+		if (dob->ob != ob)
+			continue;
+		
+		inst = MEM_callocN(sizeof(HaircutCacheInstance), "shrink wrap instance");
+		mul_m4_m4m4(inst->mat, obmat, dob->mat);
+		invert_m4_m4(inst->imat, inst->mat);
+		
+		BLI_addtail(&data->instances, inst);
+	}
+}
+
+static void haircut_data_free(HaircutCacheData *data)
+{
+	BLI_freelistN(&data->instances);
+	
+	free_bvhtree_from_mesh(&data->treedata);
+	
+	if (data->dm) {
+		data->dm->release(data->dm);
+	}
+}
+
+static void haircut_apply_vertex(HaircutCacheModifier *UNUSED(hmd), HaircutCacheData *data, HaircutCacheInstance *inst, StrandsVertex *vertex, StrandsMotionState *UNUSED(state))
+{
+//	const float *point = state->co;
+//	float *npoint = state->co;
+	const float *point = vertex->co;
+	float *npoint = vertex->co;
+	
+	BVHTreeNearest nearest = {0, };
+	float co[3];
+	
+	if (!data->treedata.tree)
+		return;
+	
+	nearest.index = -1;
+	nearest.dist_sq = FLT_MAX;
+	
+	/* lookup in target space */
+	mul_v3_m4v3(co, inst->imat, point);
+	
+	BLI_bvhtree_find_nearest(data->treedata.tree, co, &nearest, data->treedata.nearest_callback, &data->treedata);
+	if (nearest.index < 0)
+		return;
+	
+	/* convert back to world space */
+	mul_m4_v3(inst->mat, nearest.co);
+	mul_mat3_m4_v3(inst->mat, nearest.no);
+	
+	{
+		float vec[3];
+		
+		sub_v3_v3v3(vec, point, nearest.co);
+		
+		/* project along the distance vector */
+		if (dot_v3v3(vec, nearest.no) < 0.0f) {
+			sub_v3_v3v3(npoint, point, vec);
+		}
+	}
+}
+
+static void haircut_apply(HaircutCacheModifier *hmd, HaircutCacheData *data, Strands *strands)
+{
+	StrandIterator it_strand;
+	for (BKE_strand_iter_init(&it_strand, strands); BKE_strand_iter_valid(&it_strand); BKE_strand_iter_next(&it_strand)) {
+		StrandVertexIterator it_vert;
+		for (BKE_strand_vertex_iter_init(&it_vert, &it_strand); BKE_strand_vertex_iter_valid(&it_vert); BKE_strand_vertex_iter_next(&it_vert)) {
+			HaircutCacheInstance *inst;
+			
+			/* XXX this is not great, the result depends on order of instances in the duplilist ...
+			 * but good enough for single instance use case.
+			 */
+			for (inst = data->instances.first; inst; inst = inst->next) {
+				haircut_apply_vertex(hmd, data, inst, it_vert.vertex, it_vert.state);
+			}
+		}
+	}
+}
+
+static void haircut_process(HaircutCacheModifier *hmd, CacheProcessContext *UNUSED(ctx), CacheProcessData *data, int UNUSED(frame), int UNUSED(frame_prev), eCacheLibrary_EvalMode UNUSED(eval_mode))
+{
+	Object *ob = hmd->object;
+	DupliObject *dob;
+	Strands *strands;
+	DupliObjectData *target_data;
+	float mat[4][4];
+	
+	HaircutCacheData shrinkwrap;
+	
+	if (!BKE_cache_modifier_find_strands(data->dupcache, ob, hmd->hair_system, NULL, &strands, NULL))
+		return;
+	if (!BKE_cache_modifier_find_object(data->dupcache, hmd->target, &target_data))
+		return;
+	
+	for (dob = data->dupcache->duplilist.first; dob; dob = dob->next) {
+		if (dob->ob != ob)
+			continue;
+		
+		/* instances are calculated relative to the strands object */
+		invert_m4_m4(mat, dob->mat);
+		
+		memset(&shrinkwrap, 0, sizeof(shrinkwrap));
+		haircut_data_get_bvhtree(&shrinkwrap, target_data->dm, true);
+		haircut_data_get_instances(&shrinkwrap, hmd->target, mat, &data->dupcache->duplilist);
+		
+		haircut_apply(hmd, &shrinkwrap, strands);
+		
+		haircut_data_free(&shrinkwrap);
+		
+		/* XXX assume a single instance ... otherwise would just overwrite previous strands data */
+		break;
+	}
+}
+
+CacheModifierTypeInfo cacheModifierType_Haircut = {
+    /* name */              "Haircut",
+    /* structName */        "HaircutCacheModifier",
+    /* structSize */        sizeof(HaircutCacheModifier),
+
+    /* copy */              (CacheModifier_CopyFunc)haircut_copy,
+    /* foreachIDLink */     (CacheModifier_ForeachIDLinkFunc)haircut_foreach_id_link,
+    /* process */           (CacheModifier_ProcessFunc)haircut_process,
+    /* init */              (CacheModifier_InitFunc)haircut_init,
+    /* free */              (CacheModifier_FreeFunc)haircut_free,
+};
+
+/* ------------------------------------------------------------------------- */
+
 bool BKE_cache_library_uses_key(CacheLibrary *cachelib, Key *key)
 {
 	CacheModifier *md;
@@ -1674,6 +1859,7 @@ void BKE_cache_modifier_init(void)
 	cache_modifier_type_set(eCacheModifierType_ForceField, &cacheModifierType_ForceField);
 	cache_modifier_type_set(eCacheModifierType_ShrinkWrap, &cacheModifierType_ShrinkWrap);
 	cache_modifier_type_set(eCacheModifierType_StrandsKey, &cacheModifierType_StrandsKey);
+	cache_modifier_type_set(eCacheModifierType_Haircut, &cacheModifierType_Haircut);
 }
 
 /* ========================================================================= */
diff --git a/source/blender/makesdna/DNA_cache_library_types.h b/source/blender/makesdna/DNA_cache_library_types.h
index 4ae73e2..48b30d9 100644
--- a/source/blender/makesdna/DNA_cache_library_types.h
+++ b/source/blender/makesdna/DNA_cache_library_types.h
@@ -171,6 +171,7 @@ typedef enum eCacheModifier_Type {
 	eCacheModifierType_ForceField                   = 2,
 	eCacheModifierType_ShrinkWrap                   = 3,
 	eCacheModifierType_StrandsKey                   = 4,
+	eCacheModifierType_Haircut                      = 5,
 	
 	NUM_CACHE_MODIFIER_TYPES
 } eCacheModifier_Type;
@@ -268,4 +269,14 @@ typedef enum eStrandsKeyCacheModifier_Flag {
 	eStrandsKeyCacheModifier_Flag_UseMotionState        = (1 << 1),
 } eStrandsKeyCacheModifier_Flag;
 
+typedef struct HaircutCacheModifier {
+	CacheModifier modifier;
+	
+	struct Object *object;
+	int hair_system;
+	int pad;
+	
+	struct Object *target;
+} HaircutCacheModifier;
+
 #endif
diff --git a/source/blender/makesrna/intern/rna_cache_library.c b/source/blender/makesrna/intern/rna_cache_library.c
index 769f58c..5ed0d0f 100644
--- a/source/blender/makesrna/intern/rna_cache_library.c
+++ b/source/blender/makesrna/intern/rna_cache_library.c
@@ -60,6 +60,7 @@ EnumPropertyItem cache_modifier_type_items[] = {
     {eCacheModifierType_ForceField, "FORCE_FIELD", ICON_FORCE_FORCE, "Force Field", ""},
     {eCacheModifierType_ShrinkWrap, "SHRINK_WRAP", ICON_MOD_SHRINKWRAP, "Shrink Wrap", ""},
     {eCacheModifierType_StrandsKey, "STRANDS_KEY", ICON_SHAPEKEY_DATA, "Strands Key", "Shape key for strands"},
+    {eCacheModifierType_Haircut, "HAIRCUT", ICON_HAIR, "Hair Cut", "Cut strands where they intersect with an object"},
     {0, NULL, 0, NULL, NULL}
 };
 
@@ -127,6 +128,8 @@ static StructRNA *rna_CacheModifier_refine(struct PointerRNA *ptr)
 			return &RNA_ShrinkWrapCacheModifier;
 		case eCacheModifierType_StrandsKey:
 			return &RNA_StrandsKeyCacheModifier;
+		case eCacheModifierType_Haircut:
+			return &RNA_HaircutCacheModifier;
 			
 		/* Default */
 		case eCacheModifierType_None:
@@ -380,6 +383,37 @@ static PointerRNA rna_StrandsKeyCacheModifier_active_shape_key_get(PointerRNA *p
 	return keyptr;
 }
 
+static PointerRNA rna_HaircutCacheModifier_hair_system_get(PointerRNA *ptr)
+{
+	HaircutCacheModifier *hmd = ptr->data;
+	ParticleSystem *psys = hmd->object ? BLI_findlink(&hmd->object->particlesystem, hmd->hair_system) : NULL;
+	PointerRNA value;
+	
+	RNA_pointer_create(ptr->id.data, &RNA_ParticleSystem, psys, &value);
+	retur

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list