From e38a0b3748683a35601c256053f716ad8b57002f Mon Sep 17 00:00:00 2001 From: Alexander Gavrilov Date: Sun, 8 Jul 2018 13:47:26 +0300 Subject: Shrinkwrap Constraint: implement projection features from the modifier. Allow raycasting in two directions and culling front or back faces. Also implement a new Invert Cull option in both constraint and modifier that can be used to aim for faces aligned with the project axis direction when raycasting both ways. Reviewers: mont29 Differential Revision: https://developer.blender.org/D3737 --- source/blender/blenkernel/intern/constraint.c | 20 +++++++++++-- source/blender/blenkernel/intern/shrinkwrap.c | 10 +++++-- source/blender/makesdna/DNA_constraint_types.h | 18 ++++++++++- source/blender/makesdna/DNA_modifier_types.h | 3 ++ source/blender/makesrna/intern/rna_constraint.c | 40 +++++++++++++++++++++++++ source/blender/makesrna/intern/rna_modifier.c | 11 ++++--- 6 files changed, 93 insertions(+), 9 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index b1a7c98dc9c..575f534c7ca 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3533,8 +3533,24 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con, break; } - if (BKE_shrinkwrap_project_normal(0, co, no, 0.0f, &transform, treeData.tree, - &hit, treeData.raycast_callback, &treeData) == false) + 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); + + if (scon->flag & CON_SHRINKWRAP_PROJECT_OPPOSITE) { + float inv_no[3]; + negate_v3_v3(inv_no, no); + + if ((scon->flag & CON_SHRINKWRAP_PROJECT_INVERT_CULL) && (cull_mode != 0)) { + 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); + } + + if (hit.index < 0) { fail = true; break; diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 21b21d6ddd8..5408c07adf1 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -240,7 +240,7 @@ bool BKE_shrinkwrap_project_normal( BLI_space_transform_invert_normal(transf, hit_tmp.no); } - if (options & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) { + if (options & MOD_SHRINKWRAP_CULL_TARGET_MASK) { /* apply backface */ const float dot = dot_v3v3(dir, hit_tmp.no); if (((options & MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE) && dot <= 0.0f) || @@ -341,6 +341,12 @@ static void shrinkwrap_calc_normal_projection_cb_ex( float inv_no[3]; negate_v3_v3(inv_no, tmp_no); + char options = calc->smd->shrinkOpts; + + if ((options & MOD_SHRINKWRAP_INVERT_CULL_TARGET) && (options & MOD_SHRINKWRAP_CULL_TARGET_MASK)) { + options ^= MOD_SHRINKWRAP_CULL_TARGET_MASK; + } + if (aux_tree) { BKE_shrinkwrap_project_normal( 0, tmp_co, inv_no, 0.0, @@ -349,7 +355,7 @@ static void shrinkwrap_calc_normal_projection_cb_ex( } BKE_shrinkwrap_project_normal( - calc->smd->shrinkOpts, tmp_co, inv_no, 0.0, + options, tmp_co, inv_no, 0.0, &calc->local2target, targ_tree, hit, targ_callback, treeData); } diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index e7d9e1fa7dd..a92899deaa8 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -429,7 +429,8 @@ typedef struct bShrinkwrapConstraint { char projAxisSpace; /* space to project axis in */ float projLimit; /* distance to search */ char shrinkMode; /* inside/outside/on surface (see MOD shrinkwrap) */ - char pad[3]; + char flag; /* options */ + char pad[2]; } bShrinkwrapConstraint; /* Follow Track constraints */ @@ -635,6 +636,21 @@ typedef enum eTrackToAxis_Modes { TRACK_nZ = 5 } eTrackToAxis_Modes; +/* Shrinkwrap flags */ +typedef enum eShrinkwrap_Flags { + /* Also raycast in the opposite direction. */ + CON_SHRINKWRAP_PROJECT_OPPOSITE = (1 << 0), + /* Invert the cull mode when projecting opposite. */ + CON_SHRINKWRAP_PROJECT_INVERT_CULL = (1 << 1), + + /* Ignore front faces in project; same value as MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE */ + CON_SHRINKWRAP_PROJECT_CULL_FRONTFACE = (1 << 3), + /* Ignore back faces in project; same value as MOD_SHRINKWRAP_CULL_TARGET_BACKFACE */ + CON_SHRINKWRAP_PROJECT_CULL_BACKFACE = (1 << 4), +} eShrinkwrap_Flags; + +#define CON_SHRINKWRAP_PROJECT_CULL_MASK (CON_SHRINKWRAP_PROJECT_CULL_FRONTFACE | CON_SHRINKWRAP_PROJECT_CULL_BACKFACE) + /* FollowPath flags */ typedef enum eFollowPath_Flags { FOLLOWPATH_FOLLOW = (1<<0), diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 811373e626c..9f7b09b4a18 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -920,8 +920,11 @@ enum { #endif MOD_SHRINKWRAP_INVERT_VGROUP = (1 << 6), + MOD_SHRINKWRAP_INVERT_CULL_TARGET = (1 << 7), }; +#define MOD_SHRINKWRAP_CULL_TARGET_MASK (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE) + /* Shrinkwrap->projAxis */ enum { MOD_SHRINKWRAP_PROJECT_OVER_NORMAL = 0, /* projection over normal is used if no axis is selected */ diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 39966983a8a..ba87d08fdac 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -396,6 +396,20 @@ static void rna_SplineIKConstraint_joint_bindings_set(PointerRNA *ptr, const flo memcpy(ikData->points, values, ikData->numpoints * sizeof(float)); } +static int rna_ShrinkwrapConstraint_face_cull_get(PointerRNA *ptr) +{ + bConstraint *con = (bConstraint *)ptr->data; + bShrinkwrapConstraint *swc = (bShrinkwrapConstraint *)con->data; + return swc->flag & CON_SHRINKWRAP_PROJECT_CULL_MASK; +} + +static void rna_ShrinkwrapConstraint_face_cull_set(struct PointerRNA *ptr, int value) +{ + bConstraint *con = (bConstraint *)ptr->data; + bShrinkwrapConstraint *swc = (bShrinkwrapConstraint *)con->data; + swc->flag = (swc->flag & ~CON_SHRINKWRAP_PROJECT_CULL_MASK) | value; +} + static bool rna_Constraint_cameraObject_poll(PointerRNA *ptr, PointerRNA value) { Object *ob = (Object *)value.data; @@ -1916,6 +1930,13 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static const EnumPropertyItem shrink_face_cull_items[] = { + {0, "OFF", 0, "Off", "No culling"}, + {CON_SHRINKWRAP_PROJECT_CULL_FRONTFACE, "FRONT", 0, "Front", "No projection when in front of the face"}, + {CON_SHRINKWRAP_PROJECT_CULL_BACKFACE, "BACK", 0, "Back", "No projection when behind the face"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "ShrinkwrapConstraint", "Constraint"); RNA_def_struct_ui_text(srna, "Shrinkwrap Constraint", "Create constraint-based shrinkwrap relationship"); RNA_def_struct_sdna_from(srna, "bShrinkwrapConstraint", "data"); @@ -1965,6 +1986,25 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.0f, 100.0f, 10, 3); RNA_def_property_ui_text(prop, "Project Distance", "Limit the distance used for projection (zero disables)"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + prop = RNA_def_property(srna, "use_project_opposite", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CON_SHRINKWRAP_PROJECT_OPPOSITE); + RNA_def_property_ui_text(prop, "Project Opposite", "Project in both specified and opposite directions"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + prop = RNA_def_property(srna, "cull_face", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, shrink_face_cull_items); + RNA_def_property_enum_funcs(prop, "rna_ShrinkwrapConstraint_face_cull_get", + "rna_ShrinkwrapConstraint_face_cull_set", NULL); + RNA_def_property_ui_text(prop, "Face Cull", + "Stop vertices from projecting to a face on the target when facing towards/away"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + prop = RNA_def_property(srna, "use_invert_cull", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CON_SHRINKWRAP_PROJECT_INVERT_CULL); + RNA_def_property_ui_text(prop, "Invert Cull", "When projecting in the opposite direction invert the face cull mode"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); } static void rna_def_constraint_damped_track(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 1755a37016a..bbb6eae8945 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -714,15 +714,13 @@ static int rna_MultiresModifier_filepath_length(PointerRNA *ptr) static int rna_ShrinkwrapModifier_face_cull_get(PointerRNA *ptr) { ShrinkwrapModifierData *swm = (ShrinkwrapModifierData *)ptr->data; - return swm->shrinkOpts & (MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE); + return swm->shrinkOpts & MOD_SHRINKWRAP_CULL_TARGET_MASK; } static void rna_ShrinkwrapModifier_face_cull_set(struct PointerRNA *ptr, int value) { ShrinkwrapModifierData *swm = (ShrinkwrapModifierData *)ptr->data; - - swm->shrinkOpts = - (swm->shrinkOpts & ~(MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE | MOD_SHRINKWRAP_CULL_TARGET_BACKFACE)) | value; + swm->shrinkOpts = (swm->shrinkOpts & ~MOD_SHRINKWRAP_CULL_TARGET_MASK) | value; } static bool rna_MeshDeformModifier_is_bound_get(PointerRNA *ptr) @@ -3273,6 +3271,11 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Positive", "Allow vertices to move in the positive direction of axis"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_invert_cull", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "shrinkOpts", MOD_SHRINKWRAP_INVERT_CULL_TARGET); + RNA_def_property_ui_text(prop, "Invert Cull", "When projecting in the negative direction invert the face cull mode"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "invert_vertex_group", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "shrinkOpts", MOD_SHRINKWRAP_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); -- cgit v1.2.3