[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