[Bf-blender-cvs] [99c738045a1] hair_guides_grooming: Align bundle root with the scalp surface and make sure rotation is consistent.

Lukas Tönne noreply at git.blender.org
Sun Jun 3 10:41:25 CEST 2018


Commit: 99c738045a15eb46ef049ae3bed9b9e120f2192e
Author: Lukas Tönne
Date:   Sun Jun 3 09:40:53 2018 +0100
Branches: hair_guides_grooming
https://developer.blender.org/rB99c738045a15eb46ef049ae3bed9b9e120f2192e

Align bundle root with the scalp surface and make sure rotation is consistent.

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

M	source/blender/blenkernel/BKE_mesh_sample.h
M	source/blender/blenkernel/intern/groom.c
M	source/blender/blenkernel/intern/mesh_sample.c

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

diff --git a/source/blender/blenkernel/BKE_mesh_sample.h b/source/blender/blenkernel/BKE_mesh_sample.h
index 8f8b8939bae..8599b5a38ad 100644
--- a/source/blender/blenkernel/BKE_mesh_sample.h
+++ b/source/blender/blenkernel/BKE_mesh_sample.h
@@ -55,7 +55,7 @@ bool BKE_mesh_sample_is_valid(const struct MeshSample *sample);
 bool BKE_mesh_sample_is_volume_sample(const struct MeshSample *sample);
 
 /* Evaluate position and normal on the given mesh */
-bool BKE_mesh_sample_eval(struct Mesh *mesh, const struct MeshSample *sample, float loc[3], float nor[3], float tang[3]);
+bool BKE_mesh_sample_eval(const struct Mesh *mesh, const struct MeshSample *sample, float loc[3], float nor[3], float tang[3]);
 
 /* Evaluate position for the given shapekey */
 bool BKE_mesh_sample_shapekey(struct Key *key, struct KeyBlock *kb, const struct MeshSample *sample, float loc[3]);
diff --git a/source/blender/blenkernel/intern/groom.c b/source/blender/blenkernel/intern/groom.c
index 33435238bff..722bca4d993 100644
--- a/source/blender/blenkernel/intern/groom.c
+++ b/source/blender/blenkernel/intern/groom.c
@@ -301,6 +301,31 @@ void BKE_groom_bind_scalp_regions(Groom *groom, bool force_rebind)
 	}
 }
 
+/* Returns the transform at the root of the bundle */
+static bool groom_get_bundle_transform_on_scalp(const GroomBundle *bundle, const Mesh *scalp, float r_loc[3], float r_rot[3][3])
+{
+	const int numshapeverts = bundle->numshapeverts;
+	if (numshapeverts == 0 || bundle->scalp_region == NULL)
+	{
+		return false;
+	}
+	
+	/* last sample is the center position */
+	const MeshSample *center_sample = &bundle->scalp_region[numshapeverts];
+	
+	if (BKE_mesh_sample_eval(scalp, center_sample, r_loc, r_rot[2], r_rot[1]))
+	{
+		cross_v3_v3v3(r_rot[0], r_rot[1], r_rot[2]);
+		return true;
+	}
+	else
+	{
+		zero_v3(r_loc);
+		unit_m3(r_rot);
+		return false;
+	}
+}
+
 static bool groom_shape_rebuild(GroomBundle *bundle, int numshapeverts, Object *scalp_ob)
 {
 	BLI_assert(bundle->scalp_region != NULL);
@@ -311,15 +336,13 @@ static bool groom_shape_rebuild(GroomBundle *bundle, int numshapeverts, Object *
 	
 	Mesh *me = scalp_ob->data;
 	
-	/* last sample is the center position */
-	MeshSample *center_sample = &bundle->scalp_region[numshapeverts];
-	float center_co[3], center_nor[3], center_tang[3], center_binor[3];
-	if (!BKE_mesh_sample_eval(me, center_sample, center_co, center_nor, center_tang))
+	float center_loc[3];
+	float center_mat[3][3];
+	if (!groom_get_bundle_transform_on_scalp(bundle, me, center_loc, center_mat))
 	{
 		result = false;
 		goto cleanup;
 	}
-	cross_v3_v3v3(center_binor, center_nor, center_tang);
 	
 	MeshSample *sample = bundle->scalp_region;
 	GroomSectionVertex *vert0 = bundle->verts;
@@ -333,12 +356,12 @@ static bool groom_shape_rebuild(GroomBundle *bundle, int numshapeverts, Object *
 			goto cleanup;
 		}
 		/* Get relative offset from the center */
-		sub_v3_v3(co, center_co);
+		sub_v3_v3(co, center_loc);
 		/* Convert mesh surface positions to 2D shape
 		 * by projecting onto the normal plane
 		 */
-		shape[i][0] = dot_v3v3(co, center_binor);
-		shape[i][1] = dot_v3v3(co, center_tang);
+		shape[i][0] = dot_v3v3(co, center_mat[0]);
+		shape[i][1] = dot_v3v3(co, center_mat[1]);
 	}
 	
 	bundle->numshapeverts = numshapeverts;
@@ -531,14 +554,31 @@ void BKE_groom_apply_constraints(Groom *groom, Mesh *scalp)
 	ListBase *bundles = (groom->editgroom ? &groom->editgroom->bundles : &groom->bundles);
 	for (GroomBundle *bundle = bundles->first; bundle; bundle = bundle->next)
 	{
-		/* For bound regions the bundle should be attached to the scalp */
-		if (scalp && bundle->scalp_region && bundle->totsections > 0)
+		if (bundle->totsections > 0)
 		{
-			float co[3], nor[3], tang[3];
-			/* Last in scalp_region is the center curve root point */
-			if (BKE_mesh_sample_eval(scalp, &bundle->scalp_region[bundle->numshapeverts], co, nor, tang))
+			GroomSection *section = &bundle->sections[0];
+			
+			if (scalp)
 			{
-				copy_v3_v3(bundle->sections[0].center, co);
+				/* For bound regions the bundle should be attached to the scalp */
+				groom_get_bundle_transform_on_scalp(bundle, scalp, section->center, section->mat);
+			}
+			else
+			{
+				if (bundle->totsections > 1)
+				{
+					/* align to the first segment */
+					float dir[3];
+					sub_v3_v3v3(dir, (section+1)->center, section->center);
+					normalize_v3(dir);
+					
+					const float dir_prev[3] = {0.0f, 1.0f, 0.0f};
+					rotation_between_vecs_to_mat3(section->mat, dir_prev, dir);
+				}
+				else
+				{
+					unit_m3(section->mat);
+				}
 			}
 		}
 	}
@@ -916,21 +956,19 @@ static void groom_eval_curve_step(float mat[3][3], const float mat_prev[3][3], c
 	mul_m3_m3m3(mat, rot, mat_prev);
 }
 
+/* Computes rotation matrices for all but the first segment of a bundle */
 static void groom_eval_section_mats(GroomBundle *bundle, int curve_res)
 {
 	const int curvesize = bundle->curvesize;
 	const int numshapeverts = bundle->numshapeverts;
 	
-	float mat[3][3];
-	unit_m3(mat); // TODO take from scalp mesh sample
-	
 	GroomSection *section = bundle->sections;
 	/* last curve cache is center curve */
 	const GroomCurveCache *cache = bundle->curvecache + bundle->curvesize * numshapeverts;
 	
-	/* align to first segment */
-	groom_eval_curve_step(mat, mat, cache[0].co, cache[1].co);
-	copy_m3_m3(section->mat, mat);
+	float mat[3][3];
+	/* initialize matrix */
+	copy_m3_m3(mat, section->mat);
 	++cache;
 	++section;
 	
@@ -979,8 +1017,6 @@ void BKE_groom_curve_cache_update(Groom *groom)
 			/* degenerate case */
 			copy_v3_v3(bundle->curvecache[numshapeverts].co, bundle->sections[0].center);
 			
-			unit_m3(bundle->sections[0].mat);
-			
 			for (int i = 0; i < numshapeverts; ++i)
 			{
 				copy_v2_v2(bundle->curvecache[i].co, bundle->verts[i].co);
diff --git a/source/blender/blenkernel/intern/mesh_sample.c b/source/blender/blenkernel/intern/mesh_sample.c
index 29bd12f538e..c0e0e0c790b 100644
--- a/source/blender/blenkernel/intern/mesh_sample.c
+++ b/source/blender/blenkernel/intern/mesh_sample.c
@@ -196,7 +196,7 @@ bool BKE_mesh_sample_is_volume_sample(const MeshSample *sample)
 
 /* Evaluate position and normal on the given mesh */
 
-bool BKE_mesh_sample_eval(Mesh *mesh, const MeshSample *sample, float loc[3], float nor[3], float tang[3])
+bool BKE_mesh_sample_eval(const Mesh *mesh, const MeshSample *sample, float loc[3], float nor[3], float tang[3])
 {
 	const MVert *mverts = mesh->mvert;
 	const unsigned int totverts = (unsigned int)mesh->totvert;



More information about the Bf-blender-cvs mailing list