Commit: e5b18390fa591c8b37b9ef9884611b2888bab188 Author: Alexander Gavrilov Date: Wed Oct 3 19:09:43 2018 +0300 Branches: blender2.8 https://developer.blender.org/rBe5b18390fa591c8b37b9ef9884611b2888bab188
Shrinkwrap: implement the use of smooth normals in constraint & modifier. - Use smooth normals to displace in Above Surface mode. - Add an option to align an axis to the normal in the constraint. I've seen people request the alignment feature, and it seems useful. For the actual aligning I use the damped track logic. In order to conveniently keep mesh data needed for normal computation together, a new data structure is introduced. Reviewers: mont29 Differential Revision: https://developer.blender.org/D3762 =================================================================== M release/scripts/startup/bl_ui/properties_constraint.py M source/blender/blenkernel/BKE_shrinkwrap.h M source/blender/blenkernel/intern/constraint.c M source/blender/blenkernel/intern/shrinkwrap.c M source/blender/depsgraph/intern/builder/deg_builder_relations.cc M source/blender/makesdna/DNA_constraint_types.h M source/blender/makesrna/intern/rna_constraint.c M source/blender/makesrna/intern/rna_modifier.c M source/blender/modifiers/intern/MOD_shrinkwrap.c =================================================================== diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py index ea3b5f000ec..4be1f55b3b8 100644 --- a/release/scripts/startup/bl_ui/properties_constraint.py +++ b/release/scripts/startup/bl_ui/properties_constraint.py @@ -769,6 +769,13 @@ class ConstraintButtonsPanel: rowsub.prop(con, "use_invert_cull") layout.prop(con, "project_limit") + if con.shrinkwrap_type in ['PROJECT', 'NEAREST_SURFACE']: + layout.prop(con, "use_track_normal") + + row = layout.row(align=True) + row.active = con.use_track_normal + row.prop(con, "track_axis", expand=True) + def DAMPED_TRACK(self, context, layout, con): self.target_template(layout, con) diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index 40f3808b94b..d1a14003b04 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -55,27 +55,25 @@ struct ShrinkwrapModifierData; struct BVHTree; struct SpaceTransform; +typedef struct ShrinkwrapTreeData { + Mesh *mesh; -typedef struct ShrinkwrapCalcData { - ShrinkwrapModifierData *smd; //shrinkwrap modifier data + BVHTree *bvh; + BVHTreeFromMesh treeData; - struct Object *ob; //object we are applying shrinkwrap to + float (*clnors)[3]; +} ShrinkwrapTreeData; - struct MVert *vert; //Array of verts being projected (to fetch normals or other data) - float (*vertexCos)[3]; //vertexs being shrinkwraped - int numVerts; +/* Checks if the modifier needs target normals with these settings. */ +bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode); - struct MDeformVert *dvert; //Pointer to mdeform array - int vgroup; //Vertex group num - bool invert_vgroup; /* invert vertex group influence */ +/* Initializes the mesh data structure from the given mesh and settings. */ +bool BKE_shrinkwrap_init_tree(struct ShrinkwrapTreeData *data, Mesh *mesh, int shrinkType, int shrinkMode, bool force_normals); - struct Mesh *target; //mesh we are shrinking to - struct SpaceTransform local2target; //transform to move between local and target space - - float keepDist; //Distance to keep above target surface (units are in local space) - -} ShrinkwrapCalcData; +/* Frees the tree data if necessary. */ +void BKE_shrinkwrap_free_tree(struct ShrinkwrapTreeData *data); +/* Implementation of the Shrinkwrap modifier */ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Scene *scene, struct Object *ob, struct Mesh *mesh, float (*vertexCos)[3], int numVerts); @@ -91,12 +89,17 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Scene */ bool BKE_shrinkwrap_project_normal( char options, const float vert[3], const float dir[3], const float ray_radius, - const struct SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, - BVHTree_RayCastCallback callback, void *userdata); + const struct SpaceTransform *transf, struct ShrinkwrapTreeData *tree, BVHTreeRayHit *hit); + +/* Computes a smooth normal of the target (if applicable) at the hit location. */ +void BKE_shrinkwrap_compute_smooth_normal( + const struct ShrinkwrapTreeData *tree, const struct SpaceTransform *transform, + int looptri_idx, const float hit_co[3], const float hit_no[3], float r_no[3]); /* Apply the shrink to surface modes to the given original coordinates and nearest point. */ void BKE_shrinkwrap_snap_point_to_surface( - int mode, const float hit_co[3], const float hit_no[3], float goal_dist, + const struct ShrinkwrapTreeData *tree, const struct SpaceTransform *transform, + int mode, int hit_idx, const float hit_co[3], const float hit_no[3], float goal_dist, const float point_co[3], float r_point_co[3]); /* diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 8e85cc39321..f343a62eaf7 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -107,6 +107,8 @@ * type-info structs. */ +static void damptrack_do_transform(float matrix[4][4], const float tarvec[3], int track_axis); + /* -------------- Naming -------------- */ /* Find the first available, non-duplicate name for a given constraint */ @@ -3417,15 +3419,18 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con, bool fail = false; float co[3] = {0.0f, 0.0f, 0.0f}; + bool track_normal = false; + float track_no[3] = {0.0f, 0.0f, 0.0f}; SpaceTransform transform; Mesh *target_eval = mesh_get_eval_final(depsgraph, DEG_get_input_scene(depsgraph), ct->tar, CD_MASK_BAREMESH); - BVHTreeFromMesh treeData = {NULL}; + copy_m4_m4(ct->matrix, cob->matrix); - unit_m4(ct->matrix); + bool do_track_normal = (scon->flag & CON_SHRINKWRAP_TRACK_NORMAL) != 0; + ShrinkwrapTreeData tree; - if (target_eval != NULL) { + if (BKE_shrinkwrap_init_tree(&tree, target_eval, scon->shrinkType, scon->shrinkMode, do_track_normal)) { BLI_space_transform_from_matrices(&transform, cob->matrix, ct->tar->obmat); switch (scon->shrinkType) { @@ -3437,19 +3442,10 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con, nearest.index = -1; nearest.dist_sq = FLT_MAX; - if (scon->shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) - BKE_bvhtree_from_mesh_get(&treeData, target_eval, BVHTREE_FROM_VERTS, 2); - else - BKE_bvhtree_from_mesh_get(&treeData, target_eval, BVHTREE_FROM_LOOPTRI, 2); - - if (treeData.tree == NULL) { - fail = true; - break; - } - BLI_space_transform_apply(&transform, co); - BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData); + BVHTreeFromMesh *treeData = &tree.treeData; + BLI_bvhtree_find_nearest(treeData->tree, co, &nearest, treeData->nearest_callback, treeData); if (nearest.index < 0) { fail = true; @@ -3457,7 +3453,13 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con, } if (scon->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE) { - BKE_shrinkwrap_snap_point_to_surface(scon->shrinkMode, nearest.co, nearest.no, scon->dist, co, co); + if (do_track_normal) { + track_normal = true; + BKE_shrinkwrap_compute_smooth_normal(&tree, NULL, nearest.index, nearest.co, nearest.no, track_no); + BLI_space_transform_invert_normal(&transform, track_no); + } + + BKE_shrinkwrap_snap_point_to_surface(&tree, NULL, scon->shrinkMode, nearest.index, nearest.co, nearest.no, scon->dist, co, co); } else { const float dist = len_v3v3(co, nearest.co); @@ -3504,16 +3506,9 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con, break; } - BKE_bvhtree_from_mesh_get(&treeData, target_eval, BVHTREE_FROM_LOOPTRI, 4); - if (treeData.tree == NULL) { - fail = true; - break; - } - char cull_mode = scon->flag & CON_SHRINKWRAP_PROJECT_CULL_MASK; - BKE_shrinkwrap_project_normal(cull_mode, co, no, 0.0f, &transform, treeData.tree, - &hit, treeData.raycast_callback, &treeData); + BKE_shrinkwrap_project_normal(cull_mode, co, no, 0.0f, &transform, &tree, &hit); if (scon->flag & CON_SHRINKWRAP_PROJECT_OPPOSITE) { float inv_no[3]; @@ -3523,8 +3518,7 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con, cull_mode ^= CON_SHRINKWRAP_PROJECT_CULL_MASK; } - BKE_shrinkwrap_project_normal(cull_mode, co, inv_no, 0.0f, &transform, treeData.tree, - &hit, treeData.raycast_callback, &treeData); + BKE_shrinkwrap_project_normal(cull_mode, co, inv_no, 0.0f, &transform, &tree, &hit); } if (hit.index < 0) { @@ -3532,12 +3526,17 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con, break; } - BKE_shrinkwrap_snap_point_to_surface(scon->shrinkMode, hit.co, hit.no, scon->dist, co, co); + if (do_track_normal) { + track_normal = true; + BKE_shrinkwrap_compute_smooth_normal(&tree, &transform, hit.index, hit.co, hit.no, track_no); + } + + BKE_shrinkwrap_snap_point_to_surface(&tree, &transform, scon->shrinkMode, hit.index, hit.co, hit.no, scon->dist, co, co); break; } } - free_bvhtree_from_mesh(&treeData); + BKE_shrinkwrap_free_tree(&tree); if (fail == true) { /* Don't move the point */ @@ -3547,6 +3546,11 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con, /* co is in local object coordinates, change it to global and update target position */ mul_m4_v3(cob->matrix, co); copy_v3_v3(ct->matrix[3], co); + + if (track_normal) { + mul_mat3_m4_v3(cob->matrix, track_no); + damptrack_do_transform(ct->matrix, track_no, scon->trackAxis); + } } } } @@ -3557,7 +3561,7 @@ static void shrinkwrap_evaluate(bConstraint *UNUSED(con), bConstraintOb *cob, Li /* only evaluate if there is a target */ if (VALID_CONS_TARGET(ct)) { - copy_v3_v3(cob->matrix[3], ct->matrix[3]); + copy_m4_m4(cob->matrix, ct->matrix); } } @@ -3631,7 +3635,22 @@ static void damptrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t bConstraintTarget *ct = targets->first; if (VALID_CONS_TARGET(ct)) { - float obvec[3], tarvec[3], obloc[3]; + float tarvec[3]; + + /* find the (unit) direction vector going from the owner to the target */ + sub_v3_v3v3(tarvec, ct->matrix[3], cob->matrix[3]); + + damptrack_do_transform(cob->matrix, tarvec, data->trackflag); + } +} + +static void damptrack_do_transform(float matrix[4][4], const float tarvec_in[3], int track_axis) +{ + /* find the (unit) direction vector going from the owner to the target */ + float tarvec[3]; + + if (normalize_v3_v3(tarvec, tarvec_in) != 0.0f) { + float obvec[3], obloc @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] https://lists.blender.org/mailman/listinfo/bf-blender-cvs
