Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/modifiers/intern/MOD_simpledeform.c')
-rw-r--r--source/blender/modifiers/intern/MOD_simpledeform.c185
1 files changed, 131 insertions, 54 deletions
diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c
index 379eaea5b0c..71109922f11 100644
--- a/source/blender/modifiers/intern/MOD_simpledeform.c
+++ b/source/blender/modifiers/intern/MOD_simpledeform.c
@@ -32,7 +32,6 @@
* \ingroup modifiers
*/
-
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -51,9 +50,33 @@
#define BEND_EPS 0.000001f
+/* Re-maps the indicies for X Y Z by shifting them up and wrapping, such that
+ * X = Y, Y = Z, Z = X (for X axis), and X = Z, Y = X, Z = Y (for Y axis). This
+ * exists because the deformations (excluding bend) are based on the Z axis.
+ * Having this helps avoid long, drawn out switches. */
+static const uint axis_map_table[3][3] = {
+ {1, 2, 0},
+ {2, 0, 1},
+ {0, 1, 2},
+};
+
+BLI_INLINE void copy_v3_v3_map(float a[3], const float b[3], const uint map[3])
+{
+ a[0] = b[map[0]];
+ a[1] = b[map[1]];
+ a[2] = b[map[2]];
+}
+
+BLI_INLINE void copy_v3_v3_unmap(float a[3], const float b[3], const uint map[3])
+{
+ a[map[0]] = b[0];
+ a[map[1]] = b[1];
+ a[map[2]] = b[2];
+}
+
/* Clamps/Limits the given coordinate to: limits[0] <= co[axis] <= limits[1]
* The amount of clamp is saved on dcut */
-static void axis_limit(int axis, const float limits[2], float co[3], float dcut[3])
+static void axis_limit(const int axis, const float limits[2], float co[3], float dcut[3])
{
float val = co[axis];
if (limits[0] > val) val = limits[0];
@@ -63,7 +86,7 @@ static void axis_limit(int axis, const float limits[2], float co[3], float dcut[
co[axis] = val;
}
-static void simpleDeform_taper(const float factor, const float dcut[3], float r_co[3])
+static void simpleDeform_taper(const float factor, const int UNUSED(axis), const float dcut[3], float r_co[3])
{
float x = r_co[0], y = r_co[1], z = r_co[2];
float scale = z * factor;
@@ -72,14 +95,10 @@ static void simpleDeform_taper(const float factor, const float dcut[3], float r_
r_co[1] = y + y * scale;
r_co[2] = z;
- {
- r_co[0] += dcut[0];
- r_co[1] += dcut[1];
- r_co[2] += dcut[2];
- }
+ add_v3_v3(r_co, dcut);
}
-static void simpleDeform_stretch(const float factor, const float dcut[3], float r_co[3])
+static void simpleDeform_stretch(const float factor, const int UNUSED(axis), const float dcut[3], float r_co[3])
{
float x = r_co[0], y = r_co[1], z = r_co[2];
float scale;
@@ -90,14 +109,10 @@ static void simpleDeform_stretch(const float factor, const float dcut[3], float
r_co[1] = y * scale;
r_co[2] = z * (1.0f + factor);
- {
- r_co[0] += dcut[0];
- r_co[1] += dcut[1];
- r_co[2] += dcut[2];
- }
+ add_v3_v3(r_co, dcut);
}
-static void simpleDeform_twist(const float factor, const float *dcut, float r_co[3])
+static void simpleDeform_twist(const float factor, const int UNUSED(axis), const float *dcut, float r_co[3])
{
float x = r_co[0], y = r_co[1], z = r_co[2];
float theta, sint, cost;
@@ -110,32 +125,58 @@ static void simpleDeform_twist(const float factor, const float *dcut, float r_co
r_co[1] = x * sint + y * cost;
r_co[2] = z;
- {
- r_co[0] += dcut[0];
- r_co[1] += dcut[1];
- r_co[2] += dcut[2];
- }
+ add_v3_v3(r_co, dcut);
}
-static void simpleDeform_bend(const float factor, const float dcut[3], float r_co[3])
+static void simpleDeform_bend(const float factor, const int axis, const float dcut[3], float r_co[3])
{
float x = r_co[0], y = r_co[1], z = r_co[2];
float theta, sint, cost;
BLI_assert(!(fabsf(factor) < BEND_EPS));
- theta = x * factor;
+ switch (axis) {
+ case 0:
+ ATTR_FALLTHROUGH;
+ case 1:
+ theta = z * factor;
+ break;
+ default:
+ theta = x * factor;
+ }
sint = sinf(theta);
cost = cosf(theta);
- r_co[0] = -(y - 1.0f / factor) * sint;
- r_co[1] = (y - 1.0f / factor) * cost + 1.0f / factor;
- r_co[2] = z;
-
- {
- r_co[0] += cost * dcut[0];
- r_co[1] += sint * dcut[0];
- r_co[2] += dcut[2];
+ switch (axis) {
+ case 0:
+ r_co[0] = x;
+ r_co[1] = (y - 1.0f / factor) * cost + 1.0f / factor;
+ r_co[2] = -(y - 1.0f / factor) * sint;
+ {
+ r_co[0] += dcut[0];
+ r_co[1] += sint * dcut[2];
+ r_co[2] += cost * dcut[2];
+ }
+ break;
+ case 1:
+ r_co[0] = (x - 1.0f / factor) * cost + 1.0f / factor;
+ r_co[1] = y;
+ r_co[2] = -(x - 1.0f / factor) * sint;
+ {
+ r_co[0] += sint * dcut[2];
+ r_co[1] += dcut[1];
+ r_co[2] += cost * dcut[2];
+ }
+ break;
+ default:
+ r_co[0] = -(y - 1.0f / factor) * sint;
+ r_co[1] = (y - 1.0f / factor) * cost + 1.0f / factor;
+ r_co[2] = z;
+ {
+ r_co[0] += cost * dcut[0];
+ r_co[1] += sint * dcut[0];
+ r_co[2] += dcut[2];
+ }
}
}
@@ -145,16 +186,36 @@ static void simpleDeform_bend(const float factor, const float dcut[3], float r_c
static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
- static const float lock_axis[2] = {0.0f, 0.0f};
+ const float base_limit[2] = {0.0f, 0.0f};
int i;
- int limit_axis = 0;
float smd_limit[2], smd_factor;
SpaceTransform *transf = NULL, tmp_transf;
- void (*simpleDeform_callback)(const float factor, const float dcut[3], float co[3]) = NULL; /* Mode callback */
+ void (*simpleDeform_callback)(const float factor, const int axis, const float dcut[3], float co[3]) = NULL; /* Mode callback */
int vgroup;
MDeformVert *dvert;
+ /* This is historically the lock axis, _not_ the deform axis as the name would imply */
+ const int deform_axis = smd->deform_axis;
+ int lock_axis = smd->axis;
+ if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) { /* Bend mode shouln't have any lock axis */
+ lock_axis = 0;
+ }
+ else {
+ /* Don't lock axis if it is the chosen deform axis, as this flattens
+ * the geometry */
+ if (deform_axis == 0) {
+ lock_axis &= ~MOD_SIMPLEDEFORM_LOCK_AXIS_X;
+ }
+ if (deform_axis == 1) {
+ lock_axis &= ~MOD_SIMPLEDEFORM_LOCK_AXIS_Y;
+ }
+ if (deform_axis == 2) {
+ lock_axis &= ~MOD_SIMPLEDEFORM_LOCK_AXIS_Z;
+ }
+ }
+
+
/* Safe-check */
if (smd->origin == ob) smd->origin = NULL; /* No self references */
@@ -169,11 +230,21 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
BLI_SPACE_TRANSFORM_SETUP(transf, ob, smd->origin);
}
- /* Setup vars,
- * Bend limits on X.. all other modes limit on Z */
- limit_axis = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2;
-
/* Update limits if needed */
+ int limit_axis = deform_axis;
+ if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) {
+ /* Bend is a special case. */
+ switch (deform_axis) {
+ case 0:
+ ATTR_FALLTHROUGH;
+ case 1:
+ limit_axis = 2;
+ break;
+ default:
+ limit_axis = 0;
+ }
+ }
+
{
float lower = FLT_MAX;
float upper = -FLT_MAX;
@@ -215,6 +286,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
modifier_get_vgroup(ob, dm, smd->vgroup_name, &dvert, &vgroup);
const bool invert_vgroup = (smd->flag & MOD_SIMPLEDEFORM_FLAG_INVERT_VGROUP) != 0;
+ const uint *axis_map = axis_map_table[(smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) ? deform_axis : 2];
for (i = 0; i < numVerts; i++) {
float weight = defvert_array_find_weight_safe(dvert, i, vgroup);
@@ -232,14 +304,26 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object
copy_v3_v3(co, vertexCos[i]);
- /* Apply axis limits */
- if (smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) { /* Bend mode shoulnt have any lock axis */
- if (smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut);
- if (smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut);
+ /* Apply axis limits, and axis mappings */
+ if (lock_axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) {
+ axis_limit(0, base_limit, co, dcut);
+ }
+ if (lock_axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) {
+ axis_limit(1, base_limit, co, dcut);
+ }
+ if (lock_axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Z) {
+ axis_limit(2, base_limit, co, dcut);
}
axis_limit(limit_axis, smd_limit, co, dcut);
- simpleDeform_callback(smd_factor, dcut, co); /* apply deform */
+ /* apply the deform to a mapped copy of the vertex, and then re-map it back. */
+ float co_remap[3];
+ float dcut_remap[3];
+ copy_v3_v3_map(co_remap, co, axis_map);
+ copy_v3_v3_map(dcut_remap, dcut, axis_map);
+ simpleDeform_callback(smd_factor, deform_axis, dcut_remap, co_remap); /* apply deform */
+ copy_v3_v3_unmap(co, co_remap, axis_map);
+
interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight); /* Use vertex weight has coef of linear interpolation */
if (transf) {
@@ -257,6 +341,7 @@ static void initData(ModifierData *md)
smd->mode = MOD_SIMPLEDEFORM_MODE_TWIST;
smd->axis = 0;
+ smd->deform_axis = 0;
smd->origin = NULL;
smd->factor = DEG2RADF(45.0f);
@@ -293,27 +378,19 @@ static void foreachObjectLink(
walk(userData, ob, &smd->origin, IDWALK_CB_NOP);
}
-static void updateDepgraph(ModifierData *md, DagForest *forest,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- DagNode *obNode)
+static void updateDepgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
if (smd->origin)
- dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier");
+ dag_add_relation(ctx->forest, dag_get_node(ctx->forest, smd->origin), ctx->obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier");
}
-static void updateDepsgraph(ModifierData *md,
- struct Main *UNUSED(bmain),
- struct Scene *UNUSED(scene),
- Object *UNUSED(ob),
- struct DepsNodeHandle *node)
+static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
if (smd->origin != NULL) {
- DEG_add_object_relation(node, smd->origin, DEG_OB_COMP_TRANSFORM, "SimpleDeform Modifier");
+ DEG_add_object_relation(ctx->node, smd->origin, DEG_OB_COMP_TRANSFORM, "SimpleDeform Modifier");
}
}