[Bf-blender-cvs] [a2787c1] strand_nodes: Simple contact detection method for hair editing, using the typical BVH closest point method.

Lukas Tönne noreply at git.blender.org
Sun Aug 7 10:39:42 CEST 2016


Commit: a2787c1f747ea066a65b41344f90fae22f2b5c4a
Author: Lukas Tönne
Date:   Fri Jul 29 12:12:03 2016 +0200
Branches: strand_nodes
https://developer.blender.org/rBa2787c1f747ea066a65b41344f90fae22f2b5c4a

Simple contact detection method for hair editing, using the typical BVH closest point method.

This method is just a placeholder, in the future it would be worthwhile to use Bullet collision
detection with ghost objects for this.

Also the code should eventually be abstracted a bit to make it agnostic to mesh formats, so it
can be used for BMesh as well as DNA strand data or physics simulation.

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

M	source/blender/blenkernel/BKE_editstrands.h
M	source/blender/blenkernel/intern/editstrands.c
M	source/blender/bmesh/intern/bmesh_strands_conv.c
M	source/blender/bmesh/intern/bmesh_strands_conv.h
M	source/blender/editors/hair/hair_edit.c
M	source/blender/editors/transform/transform_conversions.c
M	source/blender/physics/BPH_strands.h
M	source/blender/physics/intern/strands.cpp

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

diff --git a/source/blender/blenkernel/BKE_editstrands.h b/source/blender/blenkernel/BKE_editstrands.h
index 2fc0728..b40819d 100644
--- a/source/blender/blenkernel/BKE_editstrands.h
+++ b/source/blender/blenkernel/BKE_editstrands.h
@@ -42,10 +42,12 @@
 #include "bmesh.h"
 
 struct BMesh;
+struct CollisionContactCache;
 struct DerivedMesh;
 struct GPUStrandsConverter;
 struct Mesh;
 struct Object;
+struct Scene;
 struct Strands;
 struct StrandFiber;
 
@@ -87,7 +89,10 @@ typedef float (*BMEditStrandsLocations)[3];
 BMEditStrandsLocations BKE_editstrands_get_locations(struct BMEditStrands *edit);
 void BKE_editstrands_free_locations(BMEditStrandsLocations locs);
 
-void BKE_editstrands_solve_constraints(struct Object *ob, struct BMEditStrands *es, BMEditStrandsLocations orig);
+void BKE_editstrands_get_collision_contacts(struct Scene *scene, struct Object *ob, struct BMEditStrands *edit,
+                                            struct CollisionContactCache *cache);
+
+void BKE_editstrands_solve_constraints(struct Scene *scene, struct Object *ob, struct BMEditStrands *es, BMEditStrandsLocations orig);
 void BKE_editstrands_ensure(struct BMEditStrands *es);
 
 /* === particle conversion === */
diff --git a/source/blender/blenkernel/intern/editstrands.c b/source/blender/blenkernel/intern/editstrands.c
index a8e180c..c59604b 100644
--- a/source/blender/blenkernel/intern/editstrands.c
+++ b/source/blender/blenkernel/intern/editstrands.c
@@ -41,8 +41,10 @@
 #include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_particle_types.h"
+#include "DNA_scene_types.h"
 
 #include "BKE_bvhutils.h"
+#include "BKE_collision.h"
 #include "BKE_customdata.h"
 #include "BKE_cdderivedmesh.h"
 #include "BKE_DerivedMesh.h"
@@ -221,11 +223,82 @@ void BKE_editstrands_free_locations(BMEditStrandsLocations locs)
 	MEM_freeN(locs);
 }
 
-void BKE_editstrands_solve_constraints(Object *ob, BMEditStrands *es, BMEditStrandsLocations orig)
+static void get_dm_collision_contacts(BMEditStrands *edit, float obmat[4][4],
+                                      DerivedMesh *dm, float dm_obmat[4][4], int collider_index,
+                                      CollisionContactCache *cache)
+{
+	BMesh *bm = edit->base.bm;
+	BVHTreeFromMesh treedata = {NULL};
+	
+	bvhtree_from_mesh_looptri(&treedata, dm, 0.0, 2, 6);
+	if (!treedata.tree)
+		return;
+	
+	/* Vertices must be transformed to DM space for lookups.
+	 * Results are then transformed to world space.
+	 */
+	float dm_imat[4][4];
+	invert_m4_m4(dm_imat, dm_obmat);
+	float vertmat[4][4];
+	mul_m4_m4m4(vertmat, dm_imat, obmat);
+	
+	BMIter iter;
+	BMVert *vert;
+	int vert_index;
+	BM_ITER_MESH_INDEX(vert, &iter, bm, BM_VERTS_OF_MESH, vert_index) {
+		BVHTreeNearest nearest;
+		nearest.index = -1;
+		nearest.dist_sq = FLT_MAX;
+		
+		float co[3];
+		mul_v3_m4v3(co, vertmat, vert->co);
+		
+		float radius = BM_elem_float_data_named_get(&bm->vdata, vert, CD_PROP_FLT, CD_HAIR_RADIUS);
+		
+		BLI_bvhtree_find_nearest(treedata.tree, co, &nearest, treedata.nearest_callback, &treedata);
+		
+		if (nearest.index != -1) {
+			CollisionContactPoint *pt = BKE_collision_cache_add(cache, 0, collider_index,
+			                                                    vert_index, nearest.index);
+			mul_v3_m4v3(pt->point_world_a, dm_imat, co);
+			mul_v3_m4v3(pt->point_world_b, dm_imat, nearest.co);
+			mul_v3_mat3_m4v3(pt->normal_world_b, dm_imat, nearest.no);
+			
+			float vec[3];
+			sub_v3_v3v3(vec, co, nearest.co);
+			mul_mat3_m4_v3(dm_imat, vec);
+			float dist = len_v3(vec);
+			if (dot_v3v3(vec, nearest.no) >= 0.0f)
+				pt->distance = dist - radius;
+			else
+				pt->distance = -dist - radius;
+		}
+	}
+	
+	free_bvhtree_from_mesh(&treedata);
+}
+
+void BKE_editstrands_get_collision_contacts(Scene *scene, Object *ob, BMEditStrands *edit,
+                                            CollisionContactCache *cache)
+{
+	HairEditSettings *settings = &scene->toolsettings->hair_edit;
+	
+	if (settings->flag & HAIR_EDIT_DEFLECT_SCALP) {
+		DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+		get_dm_collision_contacts(edit, ob->obmat, dm, ob->obmat, 0, cache);
+	}
+	
+	if (settings->deflect_group) {
+		/* TODO add collision group contacts */
+		/* ... */
+	}
+}
+
+void BKE_editstrands_solve_constraints(Scene *scene, Object *ob, BMEditStrands *es, BMEditStrandsLocations orig)
 {
 	BKE_editstrands_ensure(es);
 	
-	BPH_strands_solve_constraints(ob, es, orig);
+	BPH_strands_solve_constraints(scene, ob, es, orig);
 }
 
 static void editstrands_calc_segment_lengths(BMesh *bm)
diff --git a/source/blender/bmesh/intern/bmesh_strands_conv.c b/source/blender/bmesh/intern/bmesh_strands_conv.c
index f15455d..cce8945 100644
--- a/source/blender/bmesh/intern/bmesh_strands_conv.c
+++ b/source/blender/bmesh/intern/bmesh_strands_conv.c
@@ -51,6 +51,7 @@ const char *CD_HAIR_SEGMENT_LENGTH = "HAIR_SEGMENT_LENGTH";
 const char *CD_HAIR_MASS = "HAIR_MASS";
 const char *CD_HAIR_WEIGHT = "HAIR_WEIGHT";
 const char *CD_HAIR_ROOT_LOCATION = "HAIR_ROOT_LOCATION";
+const char *CD_HAIR_RADIUS = "HAIR_RADIUS";
 
 /* ------------------------------------------------------------------------- */
 
@@ -90,6 +91,9 @@ void BM_strands_cd_flag_apply(BMesh *bm, const char UNUSED(cd_flag))
 	if (CustomData_get_named_layer_index(&bm->vdata, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH) < 0) {
 		BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_FLT, CD_HAIR_SEGMENT_LENGTH);
 	}
+	if (CustomData_get_named_layer_index(&bm->vdata, CD_PROP_FLT, CD_HAIR_RADIUS) < 0) {
+		BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_FLT, CD_HAIR_RADIUS);
+	}
 }
 
 char BM_strands_cd_flag_from_bmesh(BMesh *UNUSED(bm))
diff --git a/source/blender/bmesh/intern/bmesh_strands_conv.h b/source/blender/bmesh/intern/bmesh_strands_conv.h
index 498af26..5dea2a6 100644
--- a/source/blender/bmesh/intern/bmesh_strands_conv.h
+++ b/source/blender/bmesh/intern/bmesh_strands_conv.h
@@ -44,6 +44,7 @@ extern const char *CD_HAIR_SEGMENT_LENGTH;
 extern const char *CD_HAIR_MASS;
 extern const char *CD_HAIR_WEIGHT;
 extern const char *CD_HAIR_ROOT_LOCATION;
+extern const char *CD_HAIR_RADIUS;
 
 void BM_strands_cd_validate(struct BMesh *bm);
 void BM_strands_cd_flag_ensure(struct BMesh *bm, const char cd_flag);
diff --git a/source/blender/editors/hair/hair_edit.c b/source/blender/editors/hair/hair_edit.c
index 7c41354..be70a4e 100644
--- a/source/blender/editors/hair/hair_edit.c
+++ b/source/blender/editors/hair/hair_edit.c
@@ -346,7 +346,7 @@ static bool hair_stroke_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
 		bool step_updated = hair_brush_step(&tool_data);
 		
 		if (step_updated)
-			BKE_editstrands_solve_constraints(ob, edit, NULL);
+			BKE_editstrands_solve_constraints(scene, ob, edit, NULL);
 		
 		updated |= step_updated;
 	}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 463b3f9..ccd0038 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2166,7 +2166,7 @@ void flushTransStrands(TransInfo *t)
 	BMEditStrands *edit = BKE_editstrands_from_object(ob);
 	BMEditStrandsLocations origlocs = t->custom.type.data;
 	
-	BKE_editstrands_solve_constraints(ob, edit, origlocs);
+	BKE_editstrands_solve_constraints(scene, ob, edit, origlocs);
 }
 
 /* ********************* mesh ****************** */
diff --git a/source/blender/physics/BPH_strands.h b/source/blender/physics/BPH_strands.h
index 068c47f..bc829fd 100644
--- a/source/blender/physics/BPH_strands.h
+++ b/source/blender/physics/BPH_strands.h
@@ -32,10 +32,11 @@
 extern "C" {
 #endif
 
-struct Object;
 struct BMEditStrands;
+struct Object;
+struct Scene;
 
-void BPH_strands_solve_constraints(struct Object *ob, struct BMEditStrands *es, float (*orig)[3]);
+void BPH_strands_solve_constraints(struct Scene *scene, struct Object *ob, struct BMEditStrands *es, float (*orig)[3]);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/physics/intern/strands.cpp b/source/blender/physics/intern/strands.cpp
index 2049d6d..1d7c2eb 100644
--- a/source/blender/physics/intern/strands.cpp
+++ b/source/blender/physics/intern/strands.cpp
@@ -36,8 +36,10 @@ extern "C" {
 
 #include "DNA_customdata_types.h"
 #include "DNA_object_types.h"
+#include "DNA_scene_types.h"
 
 #include "BKE_bvhutils.h"
+#include "BKE_collision.h"
 #include "BKE_customdata.h"
 #include "BKE_cdderivedmesh.h"
 #include "BKE_DerivedMesh.h"
@@ -410,8 +412,10 @@ static void strands_solve_inverse_kinematics(Object *ob, BMEditStrands *edit, fl
 	}
 }
 
-void BPH_strands_solve_constraints(Object *ob, BMEditStrands *edit, float (*orig)[3])
+void BPH_strands_solve_constraints(Scene *scene, Object *ob, BMEditStrands *edit, float (*orig)[3])
 {
+	HairEditSettings *settings = &scene->toolsettings->hair_edit;
+	
 	strands_apply_root_locations(edit);
 	
 	if (true) {
@@ -421,4 +425,14 @@ void BPH_strands_solve_constraints(Object *ob, BMEditStrands *edit, float (*orig
 		if (orig)
 			strands_solve_inverse_kinematics(ob, edit, orig);
 	}
+	
+	
+	/* Deflection */
+	if (settings->flag & HAIR_EDIT_USE_DEFLECT) {
+		CollisionContactCache *contacts = BKE_collision_cache_create();
+		
+		BKE_editstrands_get_collision_contacts(scene, ob, edit, contacts);
+		
+		BKE_collision_cache_free(contacts);
+	}
 }




More information about the Bf-blender-cvs mailing list