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
This commit is contained in:
parent
be0e58d980
commit
e38a0b3748
|
@ -758,6 +758,15 @@ class ConstraintButtonsPanel:
|
|||
split.label(text="Axis Space:")
|
||||
rowsub = split.row()
|
||||
rowsub.prop(con, "project_axis_space", text="")
|
||||
split = layout.split(factor=0.4)
|
||||
split.label(text="Face Culling:")
|
||||
rowsub = split.row()
|
||||
rowsub.prop(con, "cull_face", expand=True)
|
||||
row = layout.row()
|
||||
row.prop(con, "use_project_opposite")
|
||||
rowsub = row.row()
|
||||
rowsub.active = con.use_project_opposite and con.cull_face != 'OFF'
|
||||
rowsub.prop(con, "use_invert_cull")
|
||||
layout.prop(con, "project_limit")
|
||||
|
||||
def DAMPED_TRACK(self, context, layout, con):
|
||||
|
|
|
@ -848,6 +848,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
|||
col.prop(md, "use_negative_direction")
|
||||
col.prop(md, "use_positive_direction")
|
||||
|
||||
subcol = col.column()
|
||||
subcol.active = md.use_negative_direction and md.cull_face != 'OFF'
|
||||
subcol.prop(md, "use_invert_cull")
|
||||
|
||||
col = split.column()
|
||||
col.label(text="Cull Faces:")
|
||||
col.prop(md, "cull_face", expand=True)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue