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
path: root/source
diff options
context:
space:
mode:
authorBen Batt <benbatt@gmail.com>2007-04-29 22:13:55 +0400
committerBen Batt <benbatt@gmail.com>2007-04-29 22:13:55 +0400
commit125c77bca330830c5fe6dd32cc3b5d3f4c716bbb (patch)
tree7e98ea00dcf35e3f8f823ad3466ed2ab8878d55e /source
parentd0ac7ef08742b439187837064da2ad2abcefb831 (diff)
Patch #6113 - Cast & Smooth modifiers
This patch adds two modifiers: Cast and Smooth. The Cast modifier deforms vertices into a sphere, cylinder or cuboid shape. The location and orientation of the projection shape can be controlled by a specified control object. The Smooth modifier smooths the mesh in a similar way to the Edit mode "Smooth" button. Thanks to Willian Padovani Germano (ianwill) for the patch!
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/modifier.c825
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h38
-rw-r--r--source/blender/python/api2_2x/Modifier.c182
-rw-r--r--source/blender/python/api2_2x/doc/Modifier.py27
-rw-r--r--source/blender/src/buttons_editing.c36
5 files changed, 1101 insertions, 7 deletions
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 2d7113f7cc0..543c1362023 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -3318,6 +3318,809 @@ exit:
return result;
}
+/* Smooth */
+
+static void smoothModifier_initData(ModifierData *md)
+{
+ SmoothModifierData *smd = (SmoothModifierData*) md;
+
+ smd->fac = 0.5f;
+ smd->repeat = 1;
+ smd->flag = MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z;
+ smd->defgrp_name[0] = '\0';
+}
+
+static void smoothModifier_copyData(ModifierData *md, ModifierData *target)
+{
+ SmoothModifierData *smd = (SmoothModifierData*) md;
+ SmoothModifierData *tsmd = (SmoothModifierData*) target;
+
+ tsmd->fac = smd->fac;
+ tsmd->repeat = smd->repeat;
+ tsmd->flag = smd->flag;
+ strncpy(tsmd->defgrp_name, smd->defgrp_name, 32);
+}
+
+int smoothModifier_isDisabled(ModifierData *md)
+{
+ SmoothModifierData *smd = (SmoothModifierData*) md;
+ short flag;
+
+ flag = smd->flag & (MOD_SMOOTH_X|MOD_SMOOTH_Y|MOD_SMOOTH_Z);
+
+ /* disable if modifier is off for X, Y and Z or if factor is 0 */
+ if((smd->fac == 0.0f) || flag == 0) return 1;
+
+ return 0;
+}
+
+CustomDataMask smoothModifier_requiredDataMask(ModifierData *md)
+{
+ SmoothModifierData *smd = (SmoothModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(smd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static void smoothModifier_do(
+ SmoothModifierData *smd, Object *ob, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts)
+{
+ MDeformVert *dvert = NULL;
+ MEdge *medges = NULL;
+
+ int i, j, numDMEdges, defgrp_index;
+ unsigned char *uctmp;
+ float *ftmp, fac, facm;
+
+ ftmp = (float*)MEM_callocN(3*sizeof(float)*numVerts,
+ "smoothmodifier_f");
+ if (!ftmp) return;
+ uctmp = (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts,
+ "smoothmodifier_uc");
+ if (!uctmp) {
+ if (ftmp) MEM_freeN(ftmp);
+ return;
+ }
+
+ fac = smd->fac;
+ facm = 1 - fac;
+
+ medges = CDDM_get_edges(dm);
+ numDMEdges = dm->getNumEdges(dm);
+
+ defgrp_index = -1;
+
+ if (smd->defgrp_name[0]) {
+ bDeformGroup *def;
+
+ for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
+ if (!strcmp(def->name, smd->defgrp_name)) {
+ defgrp_index = i;
+ break;
+ }
+ }
+ }
+
+ if (defgrp_index >= 0)
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+ /* NOTICE: this can be optimized a little bit by moving the
+ * if (dvert) out of the loop, if needed */
+ for (j = 0; j < smd->repeat; j++) {
+ for (i = 0; i < numDMEdges; i++) {
+ float fvec[3];
+ float *v1, *v2;
+ unsigned int idx1, idx2;
+
+ idx1 = medges[i].v1;
+ idx2 = medges[i].v2;
+
+ v1 = vertexCos[idx1];
+ v2 = vertexCos[idx2];
+
+ fvec[0] = (v1[0] + v2[0]) / 2.0;
+ fvec[1] = (v1[1] + v2[1]) / 2.0;
+ fvec[2] = (v1[2] + v2[2]) / 2.0;
+
+ v1 = &ftmp[idx1*3];
+ v2 = &ftmp[idx2*3];
+
+ if (uctmp[idx1] < 255) {
+ uctmp[idx1]++;
+ VecAddf(v1, v1, fvec);
+ }
+ if (uctmp[idx2] < 255) {
+ uctmp[idx2]++;
+ VecAddf(v2, v2, fvec);
+ }
+ }
+
+ if (dvert) {
+ for (i = 0; i < numVerts; i++) {
+ MDeformWeight *dw = NULL;
+ float f, fm, facw, *fp, *v;
+ int k;
+ short flag = smd->flag;
+
+ v = vertexCos[i];
+ fp = &ftmp[i*3];
+
+ for (k = 0; k < dvert[i].totweight; ++k) {
+ if(dvert[i].dw[k].def_nr == defgrp_index) {
+ dw = &dvert[i].dw[k];
+ break;
+ }
+ }
+ if (!dw) continue;
+
+ f = fac * dw->weight;
+ fm = 1.0f - f;
+
+ /* fp is the sum of uctmp[i] verts, so must be averaged */
+ facw = 0.0f;
+ if (uctmp[i])
+ facw = f / (float)uctmp[i];
+
+ if (flag & MOD_SMOOTH_X)
+ v[0] = fm * v[0] + facw * fp[0];
+ if (flag & MOD_SMOOTH_Y)
+ v[1] = fm * v[1] + facw * fp[1];
+ if (flag & MOD_SMOOTH_Z)
+ v[2] = fm * v[2] + facw * fp[2];
+ }
+ }
+ else { /* no vertex group */
+ for (i = 0; i < numVerts; i++) {
+ float facw, *fp, *v;
+ short flag = smd->flag;
+
+ v = vertexCos[i];
+ fp = &ftmp[i*3];
+
+ /* fp is the sum of uctmp[i] verts, so must be averaged */
+ facw = 0.0f;
+ if (uctmp[i])
+ facw = fac / (float)uctmp[i];
+
+ if (flag & MOD_SMOOTH_X)
+ v[0] = facm * v[0] + facw * fp[0];
+ if (flag & MOD_SMOOTH_Y)
+ v[1] = facm * v[1] + facw * fp[1];
+ if (flag & MOD_SMOOTH_Z)
+ v[2] = facm * v[2] + facw * fp[2];
+ }
+
+ }
+
+ memset(ftmp, 0, 3*sizeof(float)*numVerts);
+ memset(uctmp, 0, sizeof(unsigned char)*numVerts);
+ }
+
+ MEM_freeN(ftmp);
+ MEM_freeN(uctmp);
+}
+
+static void smoothModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm;
+
+ if(derivedData) dm = CDDM_copy(derivedData);
+ else dm = CDDM_from_mesh(ob->data, ob);
+
+ CDDM_apply_vert_coords(dm, vertexCos);
+ CDDM_calc_normals(dm);
+
+ smoothModifier_do((SmoothModifierData *)md, ob, dm,
+ vertexCos, numVerts);
+
+ dm->release(dm);
+}
+
+static void smoothModifier_deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm;
+
+ if(derivedData) dm = CDDM_copy(derivedData);
+ else dm = CDDM_from_editmesh(editData, ob->data);
+
+ CDDM_apply_vert_coords(dm, vertexCos);
+ CDDM_calc_normals(dm);
+
+ smoothModifier_do((SmoothModifierData *)md, ob, dm,
+ vertexCos, numVerts);
+
+ dm->release(dm);
+}
+
+/* Cast */
+
+static void castModifier_initData(ModifierData *md)
+{
+ CastModifierData *cmd = (CastModifierData*) md;
+
+ cmd->fac = 0.5f;
+ cmd->radius = 0.0f;
+ cmd->size = 0.0f;
+ cmd->flag = MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z
+ | MOD_CAST_SIZE_FROM_RADIUS;
+ cmd->type = MOD_CAST_TYPE_SPHERE;
+ cmd->defgrp_name[0] = '\0';
+ cmd->object = NULL;
+}
+
+
+static void castModifier_copyData(ModifierData *md, ModifierData *target)
+{
+ CastModifierData *cmd = (CastModifierData*) md;
+ CastModifierData *tcmd = (CastModifierData*) target;
+
+ tcmd->fac = cmd->fac;
+ tcmd->radius = cmd->radius;
+ tcmd->size = cmd->size;
+ tcmd->flag = cmd->flag;
+ tcmd->type = cmd->type;
+ tcmd->object = cmd->object;
+ strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32);
+}
+
+int castModifier_isDisabled(ModifierData *md)
+{
+ CastModifierData *cmd = (CastModifierData*) md;
+ short flag;
+
+ flag = cmd->flag & (MOD_CAST_X|MOD_CAST_Y|MOD_CAST_Z);
+
+ if((cmd->fac == 0.0f) || flag == 0) return 1;
+
+ return 0;
+}
+
+CustomDataMask castModifier_requiredDataMask(ModifierData *md)
+{
+ CastModifierData *cmd = (CastModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ /* ask for vertexgroups if we need them */
+ if(cmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+static void castModifier_foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
+{
+ CastModifierData *cmd = (CastModifierData*) md;
+
+ walk (userData, ob, &cmd->object);
+}
+
+static void castModifier_updateDepgraph(
+ ModifierData *md, DagForest *forest, Object *ob,
+ DagNode *obNode)
+{
+ CastModifierData *cmd = (CastModifierData*) md;
+
+ if (cmd->object) {
+ DagNode *curNode = dag_get_node(forest, cmd->object);
+
+ dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
+ }
+}
+
+static void castModifier_sphere_do(
+ CastModifierData *cmd, Object *ob, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts)
+{
+ MDeformVert *dvert = NULL;
+
+ Object *ctrl_ob = NULL;
+
+ int i, defgrp_index = -1;
+ int has_radius = 0;
+ short flag, type;
+ float fac, facm, len = 0.0f;
+ float vec[3], center[3] = {0.0f, 0.0f, 0.0f};
+ float mat[4][4], imat[4][4];
+
+ fac = cmd->fac;
+ facm = 1.0f - fac;
+
+ flag = cmd->flag;
+
+ type = cmd->type; /* projection type: sphere or cylinder */
+
+ ctrl_ob = cmd->object;
+
+ /* spherify's center is {0, 0, 0} (the ob's own center in its local
+ * space), by default, but if the user defined a control object,
+ * we use its location, transformed to ob's local space */
+ if (ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat);
+ Mat4MulMat4(mat, ob->obmat, ctrl_ob->imat);
+ Mat4Invert(imat, mat);
+ }
+
+ Mat4Invert(ob->imat, ob->obmat);
+ VECCOPY(center, ctrl_ob->obmat[3]);
+ Mat4MulVecfl(ob->imat, center);
+ }
+
+ /* now we check which options the user wants */
+
+ /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
+ /* 2) cmd->radius > 0.0f: only the vertices within this radius from
+ * the center of the effect should be deformed */
+ if (cmd->radius > FLT_EPSILON) has_radius = 1;
+
+ /* 3) if we were given a vertex group name,
+ * only those vertices should be affected */
+ if (cmd->defgrp_name[0]) {
+ bDeformGroup *def;
+
+ for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
+ if (!strcmp(def->name, cmd->defgrp_name)) {
+ defgrp_index = i;
+ break;
+ }
+ }
+ }
+
+ if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+ if(cmd->flag & MOD_CAST_SIZE_FROM_RADIUS) {
+ len = cmd->radius;
+ }
+ else {
+ len = cmd->size;
+ }
+
+ if(len <= 0) {
+ for (i = 0; i < numVerts; i++) {
+ len += VecLenf(center, vertexCos[i]);
+ }
+ len /= numVerts;
+
+ if (len == 0.0f) len = 10.0f;
+ }
+
+ /* ready to apply the effect, one vertex at a time;
+ * tiny optimization: the code is separated (with parts repeated)
+ * in two possible cases:
+ * with or w/o a vgroup. With lots of if's in the code below,
+ * further optimizations are possible, if needed */
+ if (dvert) { /* with a vgroup */
+ float fac_orig = fac;
+ for (i = 0; i < numVerts; i++) {
+ MDeformWeight *dw = NULL;
+ int j;
+ float tmp_co[3];
+
+ VECCOPY(tmp_co, vertexCos[i]);
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ Mat4MulVecfl(mat, tmp_co);
+ } else {
+ VecSubf(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vec, tmp_co);
+
+ if (type == MOD_CAST_TYPE_CYLINDER)
+ vec[2] = 0.0f;
+
+ if (has_radius) {
+ if (VecLength(vec) > cmd->radius) continue;
+ }
+
+ for (j = 0; j < dvert[i].totweight; ++j) {
+ if(dvert[i].dw[j].def_nr == defgrp_index) {
+ dw = &dvert[i].dw[j];
+ break;
+ }
+ }
+ if (!dw) continue;
+
+ fac = fac_orig * dw->weight;
+ facm = 1.0f - fac;
+
+ Normalize(vec);
+
+ if (flag & MOD_CAST_X)
+ tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
+ if (flag & MOD_CAST_Y)
+ tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
+ if (flag & MOD_CAST_Z && type != MOD_CAST_TYPE_CYLINDER)
+ tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
+
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ Mat4MulVecfl(imat, tmp_co);
+ } else {
+ VecAddf(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vertexCos[i], tmp_co);
+ }
+ return;
+ }
+
+ /* no vgroup */
+ for (i = 0; i < numVerts; i++) {
+ float tmp_co[3];
+
+ VECCOPY(tmp_co, vertexCos[i]);
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ Mat4MulVecfl(mat, tmp_co);
+ } else {
+ VecSubf(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vec, tmp_co);
+
+ if (type == MOD_CAST_TYPE_CYLINDER)
+ vec[2] = 0.0f;
+
+ if (has_radius) {
+ if (VecLength(vec) > cmd->radius) continue;
+ }
+
+ Normalize(vec);
+
+ if (flag & MOD_CAST_X)
+ tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
+ if (flag & MOD_CAST_Y)
+ tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
+ if (flag & MOD_CAST_Z && type != MOD_CAST_TYPE_CYLINDER)
+ tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
+
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ Mat4MulVecfl(imat, tmp_co);
+ } else {
+ VecAddf(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vertexCos[i], tmp_co);
+ }
+}
+
+static void castModifier_cuboid_do(
+ CastModifierData *cmd, Object *ob, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts)
+{
+ MDeformVert *dvert = NULL;
+ Object *ctrl_ob = NULL;
+
+ int i, defgrp_index = -1;
+ int has_radius = 0;
+ short flag, type;
+ float fac, facm;
+ float min[3], max[3], bb[8][3];
+ float center[3] = {0.0f, 0.0f, 0.0f};
+ float mat[4][4], imat[4][4];
+
+ fac = cmd->fac;
+ facm = 1.0f - fac;
+
+ flag = cmd->flag;
+
+ type = cmd->type; /* projection type: sphere or cylinder */
+
+ ctrl_ob = cmd->object;
+
+ /* now we check which options the user wants */
+
+ /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
+ /* 2) cmd->radius > 0.0f: only the vertices within this radius from
+ * the center of the effect should be deformed */
+ if (cmd->radius > FLT_EPSILON) has_radius = 1;
+
+ /* 3) if we were given a vertex group name,
+ * only those vertices should be affected */
+ if (cmd->defgrp_name[0]) {
+ bDeformGroup *def;
+
+ for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
+ if (!strcmp(def->name, cmd->defgrp_name)) {
+ defgrp_index = i;
+ break;
+ }
+ }
+ }
+
+ if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
+ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+
+ if (ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat);
+ Mat4MulMat4(mat, ob->obmat, ctrl_ob->imat);
+ Mat4Invert(imat, mat);
+ }
+
+ Mat4Invert(ob->imat, ob->obmat);
+ VECCOPY(center, ctrl_ob->obmat[3]);
+ Mat4MulVecfl(ob->imat, center);
+ }
+
+ if((cmd->flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
+ for(i = 0; i < 3; i++) {
+ min[i] = -cmd->radius;
+ max[i] = cmd->radius;
+ }
+ } else if(!(cmd->flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
+ for(i = 0; i < 3; i++) {
+ min[i] = -cmd->size;
+ max[i] = cmd->size;
+ }
+ } else {
+ /* get bound box */
+ /* We can't use the object's bound box because other modifiers
+ * may have changed the vertex data. */
+ INIT_MINMAX(min, max);
+
+ /* Cast's center is the ob's own center in its local space,by default,
+ * but if the user defined a control object, we use its location,
+ * transformed to ob's local space. */
+ if (ctrl_ob) {
+ float vec[3];
+
+ /* let the center of the ctrl_ob be part of the bound box: */
+ DO_MINMAX(center, min, max);
+
+ for (i = 0; i < numVerts; i++) {
+ VecSubf(vec, vertexCos[i], center);
+ DO_MINMAX(vec, min, max);
+ }
+ }
+ else {
+ for (i = 0; i < numVerts; i++) {
+ DO_MINMAX(vertexCos[i], min, max);
+ }
+ }
+
+ /* we want a symmetric bound box around the origin */
+ if (fabs(min[0]) > fabs(max[0])) max[0] = fabs(min[0]);
+ if (fabs(min[1]) > fabs(max[1])) max[1] = fabs(min[1]);
+ if (fabs(min[2]) > fabs(max[2])) max[2] = fabs(min[2]);
+ min[0] = -max[0];
+ min[1] = -max[1];
+ min[2] = -max[2];
+ }
+
+ /* building our custom bounding box */
+ bb[0][0] = bb[2][0] = bb[4][0] = bb[6][0] = min[0];
+ bb[1][0] = bb[3][0] = bb[5][0] = bb[7][0] = max[0];
+ bb[0][1] = bb[1][1] = bb[4][1] = bb[5][1] = min[1];
+ bb[2][1] = bb[3][1] = bb[6][1] = bb[7][1] = max[1];
+ bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
+ bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];
+
+ /* ready to apply the effect, one vertex at a time;
+ * tiny optimization: the code is separated (with parts repeated)
+ * in two possible cases:
+ * with or w/o a vgroup. With lots of if's in the code below,
+ * further optimizations are possible, if needed */
+ if (dvert) { /* with a vgroup */
+ float fac_orig = fac;
+ for (i = 0; i < numVerts; i++) {
+ MDeformWeight *dw = NULL;
+ int j, octant, coord;
+ float d[3], dmax, apex[3], fbb;
+ float tmp_co[3];
+
+ VECCOPY(tmp_co, vertexCos[i]);
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ Mat4MulVecfl(mat, tmp_co);
+ } else {
+ VecSubf(tmp_co, tmp_co, center);
+ }
+ }
+
+ if (has_radius) {
+ if (fabs(tmp_co[0]) > cmd->radius ||
+ fabs(tmp_co[1]) > cmd->radius ||
+ fabs(tmp_co[2]) > cmd->radius) continue;
+ }
+
+ for (j = 0; j < dvert[i].totweight; ++j) {
+ if(dvert[i].dw[j].def_nr == defgrp_index) {
+ dw = &dvert[i].dw[j];
+ break;
+ }
+ }
+ if (!dw) continue;
+
+ fac = fac_orig * dw->weight;
+ facm = 1.0f - fac;
+
+ /* The algo used to project the vertices to their
+ * bounding box (bb) is pretty simple:
+ * for each vertex v:
+ * 1) find in which octant v is in;
+ * 2) find which outer "wall" of that octant is closer to v;
+ * 3) calculate factor (var fbb) to project v to that wall;
+ * 4) project. */
+
+ /* find in which octant this vertex is in */
+ octant = 0;
+ if (tmp_co[0] > 0.0f) octant += 1;
+ if (tmp_co[1] > 0.0f) octant += 2;
+ if (tmp_co[2] > 0.0f) octant += 4;
+
+ /* apex is the bb's vertex at the chosen octant */
+ VecCopyf(apex, bb[octant]);
+
+ /* find which bb plane is closest to this vertex ... */
+ d[0] = tmp_co[0] / apex[0];
+ d[1] = tmp_co[1] / apex[1];
+ d[2] = tmp_co[2] / apex[2];
+
+ /* ... (the closest has the higher (closer to 1) d value) */
+ dmax = d[0];
+ coord = 0;
+ if (d[1] > dmax) {
+ dmax = d[1];
+ coord = 1;
+ }
+ if (d[2] > dmax) {
+ /* dmax = d[2]; */ /* commented, we don't need it */
+ coord = 2;
+ }
+
+ /* ok, now we know which coordinate of the vertex to use */
+
+ if (fabs(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
+ continue;
+
+ /* finally, this is the factor we wanted, to project the vertex
+ * to its bounding box (bb) */
+ fbb = apex[coord] / tmp_co[coord];
+
+ /* calculate the new vertex position */
+ if (flag & MOD_CAST_X)
+ tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
+ if (flag & MOD_CAST_Y)
+ tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
+ if (flag & MOD_CAST_Z)
+ tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
+
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ Mat4MulVecfl(imat, tmp_co);
+ } else {
+ VecAddf(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vertexCos[i], tmp_co);
+ }
+ return;
+ }
+
+ /* no vgroup (check previous case for comments about the code) */
+ for (i = 0; i < numVerts; i++) {
+ int octant, coord;
+ float d[3], dmax, fbb, apex[3];
+ float tmp_co[3];
+
+ VECCOPY(tmp_co, vertexCos[i]);
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ Mat4MulVecfl(mat, tmp_co);
+ } else {
+ VecSubf(tmp_co, tmp_co, center);
+ }
+ }
+
+ if (has_radius) {
+ if (fabs(tmp_co[0]) > cmd->radius ||
+ fabs(tmp_co[1]) > cmd->radius ||
+ fabs(tmp_co[2]) > cmd->radius) continue;
+ }
+
+ octant = 0;
+ if (tmp_co[0] > 0.0f) octant += 1;
+ if (tmp_co[1] > 0.0f) octant += 2;
+ if (tmp_co[2] > 0.0f) octant += 4;
+
+ VecCopyf(apex, bb[octant]);
+
+ d[0] = tmp_co[0] / apex[0];
+ d[1] = tmp_co[1] / apex[1];
+ d[2] = tmp_co[2] / apex[2];
+
+ dmax = d[0];
+ coord = 0;
+ if (d[1] > dmax) {
+ dmax = d[1];
+ coord = 1;
+ }
+ if (d[2] > dmax) {
+ /* dmax = d[2]; */ /* commented, we don't need it */
+ coord = 2;
+ }
+
+ if (fabs(tmp_co[coord]) < FLT_EPSILON)
+ continue;
+
+ fbb = apex[coord] / tmp_co[coord];
+
+ if (flag & MOD_CAST_X)
+ tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
+ if (flag & MOD_CAST_Y)
+ tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
+ if (flag & MOD_CAST_Z)
+ tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
+
+ if(ctrl_ob) {
+ if(flag & MOD_CAST_USE_OB_TRANSFORM) {
+ Mat4MulVecfl(imat, tmp_co);
+ } else {
+ VecAddf(tmp_co, tmp_co, center);
+ }
+ }
+
+ VECCOPY(vertexCos[i], tmp_co);
+ }
+}
+
+static void castModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = derivedData;
+ CastModifierData *cmd = (CastModifierData *)md;
+
+ if (!dm && ob->type == OB_MESH)
+ dm = CDDM_from_mesh(ob->data, ob);
+
+ if (cmd->type == MOD_CAST_TYPE_CUBOID) {
+ castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
+ } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
+ castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
+ }
+
+ if (!derivedData && dm) dm->release(dm);
+}
+
+static void castModifier_deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = derivedData;
+ CastModifierData *cmd = (CastModifierData *)md;
+
+ if (!dm && ob->type == OB_MESH)
+ dm = CDDM_from_editmesh(editData, ob->data);
+
+ if (cmd->type == MOD_CAST_TYPE_CUBOID) {
+ castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
+ } else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
+ castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
+ }
+
+ if (!derivedData && dm) dm->release(dm);
+}
+
/* Wave */
static void waveModifier_initData(ModifierData *md)
@@ -4130,6 +4933,28 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->copyData = decimateModifier_copyData;
mti->applyModifier = decimateModifier_applyModifier;
+ mti = INIT_TYPE(Smooth);
+ mti->type = eModifierTypeType_OnlyDeform;
+ mti->flags = eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsEditmode;
+ mti->initData = smoothModifier_initData;
+ mti->copyData = smoothModifier_copyData;
+ mti->requiredDataMask = smoothModifier_requiredDataMask;
+ mti->deformVerts = smoothModifier_deformVerts;
+ mti->deformVertsEM = smoothModifier_deformVertsEM;
+
+ mti = INIT_TYPE(Cast);
+ mti->type = eModifierTypeType_OnlyDeform;
+ mti->flags = eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode;
+ mti->initData = castModifier_initData;
+ mti->copyData = castModifier_copyData;
+ mti->requiredDataMask = castModifier_requiredDataMask;
+ mti->foreachObjectLink = castModifier_foreachObjectLink;
+ mti->updateDepgraph = castModifier_updateDepgraph;
+ mti->deformVerts = castModifier_deformVerts;
+ mti->deformVertsEM = castModifier_deformVertsEM;
+
mti = INIT_TYPE(Wave);
mti->type = eModifierTypeType_OnlyDeform;
mti->flags = eModifierTypeFlag_AcceptsCVs
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index c5c37406c46..52ba7455284 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -26,6 +26,8 @@ typedef enum ModifierType {
eModifierType_EdgeSplit,
eModifierType_Displace,
eModifierType_UVProject,
+ eModifierType_Smooth,
+ eModifierType_Cast,
NUM_MODIFIER_TYPES
} ModifierType;
@@ -233,6 +235,42 @@ typedef struct DecimateModifierData {
int faceCount;
} DecimateModifierData;
+/* Smooth modifier flags */
+#define MOD_SMOOTH_X 1<<1
+#define MOD_SMOOTH_Y 1<<2
+#define MOD_SMOOTH_Z 1<<3
+
+typedef struct SmoothModifierData {
+ ModifierData modifier;
+ float fac;
+ char defgrp_name[32];
+ short flag, repeat;
+
+} SmoothModifierData;
+
+/* Cast modifier flags */
+#define MOD_CAST_X 1<<1
+#define MOD_CAST_Y 1<<2
+#define MOD_CAST_Z 1<<3
+#define MOD_CAST_USE_OB_TRANSFORM 1<<4
+#define MOD_CAST_SIZE_FROM_RADIUS 1<<5
+
+/* Cast modifier projection types */
+#define MOD_CAST_TYPE_SPHERE 0
+#define MOD_CAST_TYPE_CYLINDER 1
+#define MOD_CAST_TYPE_CUBOID 2
+
+typedef struct CastModifierData {
+ ModifierData modifier;
+
+ struct Object *object;
+ float fac;
+ float radius;
+ float size;
+ char defgrp_name[32];
+ short flag, type;
+} CastModifierData;
+
enum {
MOD_WAV_MAP_LOCAL,
MOD_WAV_MAP_GLOBAL,
diff --git a/source/blender/python/api2_2x/Modifier.c b/source/blender/python/api2_2x/Modifier.c
index 06c813e7820..694a0dbfbfe 100644
--- a/source/blender/python/api2_2x/Modifier.c
+++ b/source/blender/python/api2_2x/Modifier.c
@@ -67,14 +67,18 @@ enum mod_constants {
/*GENERIC*/
EXPP_MOD_OBJECT, /*ARMATURE, LATTICE, CURVE, BOOLEAN, ARRAY*/
- EXPP_MOD_VERTGROUP, /*ARMATURE, LATTICE, CURVE*/
+ EXPP_MOD_VERTGROUP, /*ARMATURE, LATTICE, CURVE, SMOOTH, CAST*/
EXPP_MOD_LIMIT, /*ARRAY, MIRROR*/
EXPP_MOD_FLAG, /*MIRROR, WAVE*/
EXPP_MOD_COUNT, /*DECIMATOR, ARRAY*/
EXPP_MOD_LENGTH, /*BUILD, ARRAY*/
+ EXPP_MOD_FACTOR, /*SMOOTH, CAST*/
+ EXPP_MOD_ENABLE_X, /*SMOOTH, CAST*/
+ EXPP_MOD_ENABLE_Y, /*SMOOTH, CAST*/
+ EXPP_MOD_ENABLE_Z, /*SMOOTH, CAST*/
+ EXPP_MOD_TYPES, /*SUBSURF, CAST*/
/*SUBSURF SPESIFIC*/
- EXPP_MOD_TYPES,
EXPP_MOD_LEVELS,
EXPP_MOD_RENDLEVELS,
EXPP_MOD_OPTIMAL,
@@ -126,7 +130,16 @@ enum mod_constants {
EXPP_MOD_STRENGTH,
EXPP_MOD_TEXTURE,
EXPP_MOD_MAPPING,
- EXPP_MOD_DIRECTION
+ EXPP_MOD_DIRECTION,
+
+ /* SMOOTH */
+ EXPP_MOD_REPEAT,
+
+ /* CAST */
+ EXPP_MOD_RADIUS,
+ EXPP_MOD_SIZE,
+ EXPP_MOD_USE_OB_TRANSFORM,
+ EXPP_MOD_SIZE_FROM_RADIUS
/* yet to be implemented */
/* EXPP_MOD_HOOK_,*/
@@ -548,6 +561,133 @@ static int decimate_setter( BPy_Modifier *self, int type, PyObject *value )
return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
}
+static PyObject *smooth_getter( BPy_Modifier * self, int type )
+{
+ SmoothModifierData *md = (SmoothModifierData *)(self->md);
+
+ switch( type ) {
+ case EXPP_MOD_FACTOR:
+ return PyFloat_FromDouble( (double)md->fac );
+ case EXPP_MOD_REPEAT:
+ return PyInt_FromLong( (long)md->repeat );
+ case EXPP_MOD_VERTGROUP:
+ return PyString_FromString( md->defgrp_name ) ;
+ case EXPP_MOD_ENABLE_X:
+ return EXPP_getBitfield( &md->flag, MOD_SMOOTH_X, 'h' );
+ case EXPP_MOD_ENABLE_Y:
+ return EXPP_getBitfield( &md->flag, MOD_SMOOTH_Y, 'h' );
+ case EXPP_MOD_ENABLE_Z:
+ return EXPP_getBitfield( &md->flag, MOD_SMOOTH_Z, 'h' );
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int smooth_setter( BPy_Modifier *self, int type, PyObject *value )
+{
+ SmoothModifierData *md = (SmoothModifierData *)(self->md);
+
+ switch( type ) {
+ case EXPP_MOD_FACTOR:
+ return EXPP_setFloatClamped( value, &md->fac, -10.0, 10.0 );
+ case EXPP_MOD_REPEAT:
+ return EXPP_setIValueRange( value, &md->repeat, 0, 30, 'h' );
+ case EXPP_MOD_VERTGROUP: {
+ char *name = PyString_AsString( value );
+ if( !name ) return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" );
+ BLI_strncpy( md->defgrp_name, name, sizeof( md->defgrp_name ) );
+ return 0;
+ }
+ case EXPP_MOD_ENABLE_X:
+ return EXPP_setBitfield( value, &md->flag, MOD_SMOOTH_X, 'h' );
+ case EXPP_MOD_ENABLE_Y:
+ return EXPP_setBitfield( value, &md->flag, MOD_SMOOTH_Y, 'h' );
+ case EXPP_MOD_ENABLE_Z:
+ return EXPP_setBitfield( value, &md->flag, MOD_SMOOTH_Z, 'h' );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static PyObject *cast_getter( BPy_Modifier * self, int type )
+{
+ CastModifierData *md = (CastModifierData *)(self->md);
+
+ switch( type ) {
+ case EXPP_MOD_TYPES:
+ return PyInt_FromLong( (long)md->type );
+ case EXPP_MOD_FACTOR:
+ return PyFloat_FromDouble( (double)md->fac );
+ case EXPP_MOD_RADIUS:
+ return PyFloat_FromDouble( (double)md->radius );
+ case EXPP_MOD_SIZE:
+ return PyFloat_FromDouble( (double)md->size );
+ case EXPP_MOD_OBJECT:
+ return Object_CreatePyObject( md->object );
+ case EXPP_MOD_VERTGROUP:
+ return PyString_FromString( md->defgrp_name ) ;
+ case EXPP_MOD_ENABLE_X:
+ return EXPP_getBitfield( &md->flag, MOD_CAST_X, 'h' );
+ case EXPP_MOD_ENABLE_Y:
+ return EXPP_getBitfield( &md->flag, MOD_CAST_Y, 'h' );
+ case EXPP_MOD_ENABLE_Z:
+ return EXPP_getBitfield( &md->flag, MOD_CAST_Z, 'h' );
+ case EXPP_MOD_USE_OB_TRANSFORM:
+ return EXPP_getBitfield( &md->flag, MOD_CAST_USE_OB_TRANSFORM, 'h' );
+ case EXPP_MOD_SIZE_FROM_RADIUS:
+ return EXPP_getBitfield( &md->flag, MOD_CAST_SIZE_FROM_RADIUS, 'h' );
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int cast_setter( BPy_Modifier *self, int type, PyObject *value )
+{
+ CastModifierData *md = (CastModifierData *)(self->md);
+
+ switch( type ) {
+ case EXPP_MOD_TYPES:
+ return EXPP_setIValueRange( value, &md->type, 0, MOD_CAST_TYPE_CUBOID, 'h' );
+ case EXPP_MOD_FACTOR:
+ return EXPP_setFloatClamped( value, &md->fac, -10.0, 10.0 );
+ case EXPP_MOD_RADIUS:
+ return EXPP_setFloatClamped( value, &md->radius, 0.0, 100.0 );
+ case EXPP_MOD_SIZE:
+ return EXPP_setFloatClamped( value, &md->size, 0.0, 100.0 );
+ case EXPP_MOD_OBJECT: {
+ Object *ob_new=NULL;
+ if (value == Py_None) {
+ md->object = NULL;
+ } else if (BPy_Object_Check( value )) {
+ ob_new = ((( BPy_Object * )value)->object);
+ md->object = ob_new;
+ } else {
+ return EXPP_ReturnIntError( PyExc_TypeError,
+ "Expected an Object or None value" );
+ }
+ return 0;
+ }
+ case EXPP_MOD_VERTGROUP: {
+ char *name = PyString_AsString( value );
+ if( !name ) return EXPP_ReturnIntError( PyExc_TypeError, "expected string arg" );
+ BLI_strncpy( md->defgrp_name, name, sizeof( md->defgrp_name ) );
+ return 0;
+ }
+ case EXPP_MOD_ENABLE_X:
+ return EXPP_setBitfield( value, &md->flag, MOD_CAST_X, 'h' );
+ case EXPP_MOD_ENABLE_Y:
+ return EXPP_setBitfield( value, &md->flag, MOD_CAST_Y, 'h' );
+ case EXPP_MOD_ENABLE_Z:
+ return EXPP_setBitfield( value, &md->flag, MOD_CAST_Z, 'h' );
+ case EXPP_MOD_USE_OB_TRANSFORM:
+ return EXPP_setBitfield( value, &md->flag, MOD_CAST_USE_OB_TRANSFORM, 'h' );
+ case EXPP_MOD_SIZE_FROM_RADIUS:
+ return EXPP_setBitfield( value, &md->flag, MOD_CAST_SIZE_FROM_RADIUS, 'h' );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
static PyObject *wave_getter( BPy_Modifier * self, int type )
{
WaveModifierData *md = (WaveModifierData *)(self->md);
@@ -866,6 +1006,10 @@ static PyObject *Modifier_getData( BPy_Modifier * self, PyObject * key )
return mirror_getter( self, setting );
case eModifierType_Decimate:
return decimate_getter( self, setting );
+ case eModifierType_Smooth:
+ return smooth_getter( self, setting );
+ case eModifierType_Cast:
+ return cast_getter( self, setting );
case eModifierType_Wave:
return wave_getter( self, setting );
case eModifierType_Boolean:
@@ -934,6 +1078,10 @@ static int Modifier_setData( BPy_Modifier * self, PyObject * key,
return array_setter( self, key_int, arg );
case eModifierType_Decimate:
return decimate_setter( self, key_int, arg );
+ case eModifierType_Smooth:
+ return smooth_setter( self, key_int, arg );
+ case eModifierType_Cast:
+ return cast_setter( self, key_int, arg );
case eModifierType_Wave:
return wave_setter( self, key_int, arg );
case eModifierType_Boolean:
@@ -1347,6 +1495,10 @@ static PyObject *M_Modifier_TypeDict( void )
PyInt_FromLong( eModifierType_Array ) );
PyConstant_Insert( d, "EDGESPLIT",
PyInt_FromLong( eModifierType_EdgeSplit ) );
+ PyConstant_Insert( d, "SMOOTH",
+ PyInt_FromLong( eModifierType_Smooth ) );
+ PyConstant_Insert( d, "CAST",
+ PyInt_FromLong( eModifierType_Cast ) );
}
return S;
}
@@ -1407,6 +1559,14 @@ for var in st.replace(',','').split('\n'):
PyInt_FromLong( EXPP_MOD_COUNT ) );
PyConstant_Insert( d, "LENGTH",
PyInt_FromLong( EXPP_MOD_LENGTH ) );
+ PyConstant_Insert( d, "FACTOR",
+ PyInt_FromLong( EXPP_MOD_FACTOR ) );
+ PyConstant_Insert( d, "ENABLE_X",
+ PyInt_FromLong( EXPP_MOD_ENABLE_X ) );
+ PyConstant_Insert( d, "ENABLE_Y",
+ PyInt_FromLong( EXPP_MOD_ENABLE_Y ) );
+ PyConstant_Insert( d, "ENABLE_Z",
+ PyInt_FromLong( EXPP_MOD_ENABLE_Z ) );
PyConstant_Insert( d, "TYPES",
PyInt_FromLong( EXPP_MOD_TYPES ) );
PyConstant_Insert( d, "LEVELS",
@@ -1471,6 +1631,22 @@ for var in st.replace(',','').split('\n'):
PyInt_FromLong( EXPP_MOD_MID_LEVEL ) );
PyConstant_Insert( d, "STRENGTH",
PyInt_FromLong( EXPP_MOD_STRENGTH ) );
+ PyConstant_Insert( d, "TEXTURE",
+ PyInt_FromLong( EXPP_MOD_TEXTURE ) );
+ PyConstant_Insert( d, "MAPPING",
+ PyInt_FromLong( EXPP_MOD_MAPPING ) );
+ PyConstant_Insert( d, "DIRECTION",
+ PyInt_FromLong( EXPP_MOD_DIRECTION ) );
+ PyConstant_Insert( d, "REPEAT",
+ PyInt_FromLong( EXPP_MOD_REPEAT ) );
+ PyConstant_Insert( d, "RADIUS",
+ PyInt_FromLong( EXPP_MOD_RADIUS ) );
+ PyConstant_Insert( d, "SIZE",
+ PyInt_FromLong( EXPP_MOD_SIZE ) );
+ PyConstant_Insert( d, "USE_OB_TRANSFORM",
+ PyInt_FromLong( EXPP_MOD_USE_OB_TRANSFORM ) );
+ PyConstant_Insert( d, "SIZE_FROM_RADIUS",
+ PyInt_FromLong( EXPP_MOD_SIZE_FROM_RADIUS ) );
/*End Auto generated code*/
}
return S;
diff --git a/source/blender/python/api2_2x/doc/Modifier.py b/source/blender/python/api2_2x/doc/Modifier.py
index 6d9c9de595a..1b00fce7721 100644
--- a/source/blender/python/api2_2x/doc/Modifier.py
+++ b/source/blender/python/api2_2x/doc/Modifier.py
@@ -4,7 +4,7 @@
The Blender.Modifier submodule
B{New}:
- - provides access to Blender's modifier stack
+ - Supports the new Cast and Smooth modifiers.
This module provides access to the Modifier Data in Blender.
@@ -57,6 +57,9 @@ Example::
- SUBSURF - type value for Subsurf modifiers
- WAVE - type value for Wave modifiers
- EDGESPLIT - type value for Edge Split modifiers
+ - DISPLACE - type value for Displace modifiers
+ - SMOOTH - type value for Smooth modifiers
+ - CAST - type value for Cast modifiers
@type Settings: readonly dictionary
@var Settings: Constant Modifier dict used for changing modifier settings.
@@ -66,13 +69,17 @@ Example::
- ONCAGE - Used for all modifiers (bool) If true, the modifier is enabled for the editing cage during edit mode.
- OBJECT - Used for Armature, Lattice, Curve, Boolean and Array (Object)
- - VERTGROUP - Used for Armature, Lattice and Curve (String)
+ - VERTGROUP - Used for Armature, Lattice, Curve, Smooth and Cast (String)
- LIMIT - Array and Mirror (float [0.0 - 1.0])
- FLAG - Mirror and Wave (int)
- COUNT - Decimator Polycount (readonly) and Array (int)
- LENGTH - Build [1.0-300000.0] and Array [0.0 - 10000.0] (float)
-
- - TYPES - Used for Subsurf only. Determines the subdivision algorithm. Integer: 0 = Catmull-Clark; 1 = simple subdivision.
+ - FACTOR - Smooth [-10.0, 10.0] and Cast [-10.0, 10.0] (float)
+ - ENABLE_X = Smooth and Cast (bool, default: True)
+ - ENABLE_Y = Smooth and Cast (bool, default: True)
+ - ENABLE_Z = Smooth and Cast (bool, default: True)
+ - TYPES - Subsurf and Cast. For Subsurf it determines the subdivision algorithm - (int): 0 = Catmull-Clark; 1 = simple subdivision. For Cast it determines the shape to deform to = (int): 0 = Sphere; 1 = Cylinder; 2 = Cuboid
+
- LEVELS - Used for Subsurf only (int [0 - 6]). The number of subdivision levels used for interactive display.
- RENDLEVELS - Used for Subsurf only (int [0 - 6]). The number of subdivision levels used for rendering.
- OPTIMAL - Used for Subsurf only (bool). Enables Optimal Draw.
@@ -109,6 +116,18 @@ Example::
- EDGESPLIT_ANGLE - Used for edge split only (float 0.0 - 180)
- EDGESPLIT_FROM_ANGLE - Used for edge split only, should the modifier use the edge angle (bool)
- EDGESPLIT_FROM_SHARP - Used for edge split only, should the modifier use the edge sharp flag (bool)
+
+ - UVLAYER - Used for Displace only
+ - MID_LEVEL - Used for Displace only (float [0.0, 1.0], default: 0.5)
+ - STRENGTH - Used for Displace only (float [-1000.0, 1000.0, default: 1.0)
+ - TEXTURE - Used for Displace only (string)
+ - MAPPING - Used for Displace only
+ - DIRECTION - Used for Displace only
+
+ - REPEAT - Used for Smooth only (int [0, 30], default: 1)
+
+ - RADIUS - Used for Cast only (float [0.0, 100.0], default: 0.0)
+ - USE_OB_SCALE - Used for Cast only (bool, default: False)
"""
class ModSeq:
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index c20b52b35b8..6adcdde2be9 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -1601,6 +1601,11 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
height = 114 + ((UVProjectModifierData *)md)->num_projectors * 19;
} else if (md->type==eModifierType_Decimate) {
height = 48;
+ } else if (md->type==eModifierType_Smooth) {
+ height = 86;
+ } else if (md->type==eModifierType_Cast) {
+ height = 124;
+ height += 19;
} else if (md->type==eModifierType_Wave) {
WaveModifierData *wmd = (WaveModifierData *)md;
height = 280;
@@ -1825,6 +1830,37 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiDefButF(block, NUM, B_MODIFIER_RECALC, "Ratio:", lx,(cy-=19),buttonWidth,19, &dmd->percent, 0.0, 1.0, 10, 0, "Defines the percentage of triangles to reduce to");
sprintf(str, "Face Count: %d", dmd->faceCount);
uiDefBut(block, LABEL, 1, str, lx, (cy-=19), 160,19, NULL, 0.0, 0.0, 0, 0, "Displays the current number of faces in the decimated mesh");
+ } else if (md->type==eModifierType_Smooth) {
+ SmoothModifierData *smd = (SmoothModifierData*) md;
+
+ uiDefButBitS(block, TOG, MOD_SMOOTH_X, B_MODIFIER_RECALC, "X", lx,(cy-=19),45,19, &smd->flag, 0, 0, 0, 0, "Enable X axis smoothing");
+ uiDefButBitS(block, TOG, MOD_SMOOTH_Y, B_MODIFIER_RECALC, "Y", lx+45,cy,45,19, &smd->flag, 0, 0, 0, 0, "Enable Y axis smoothing");
+ uiDefButBitS(block, TOG, MOD_SMOOTH_Z, B_MODIFIER_RECALC, "Z", lx+90,cy,45,19, &smd->flag, 0, 0, 0, 0, "Enable Z axis smoothing");
+
+ uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:", lx,(cy-=19),buttonWidth, 19, &smd->fac, -10.0, 10.0, 0.5, 0, "Define the amount of smoothing, from 0.0 to 1.0 (lower / higher values can deform the mesh)");
+ uiDefButS(block, NUM, B_MODIFIER_RECALC, "Repeat:", lx,(cy-=19),buttonWidth, 19, &smd->repeat, 0.0, 30.0, 1, 0, "Number of smoothing iterations");
+ but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &smd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to define which vertices are affected");
+ } else if (md->type==eModifierType_Cast) {
+ CastModifierData *cmd = (CastModifierData*) md;
+
+ char casttypemenu[]="Projection Type%t|Sphere%x0|Cylinder%x1|Cuboid%x2";
+ uiDefButS(block, MENU, B_MODIFIER_RECALC, casttypemenu, lx,(cy-=19),buttonWidth - 30,19, &cmd->type, 0, 0, 0, 0, "Projection type to apply");
+ uiDefButBitS(block, TOG, MOD_CAST_X, B_MODIFIER_RECALC, "X", lx,(cy-=19),45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) X axis deformation");
+ uiDefButBitS(block, TOG, MOD_CAST_Y, B_MODIFIER_RECALC, "Y", lx+45,cy,45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) Y axis deformation");
+ if (cmd->type != MOD_CAST_TYPE_CYLINDER) {
+ uiDefButBitS(block, TOG, MOD_CAST_Z, B_MODIFIER_RECALC, "Z", lx+90,cy,45,19, &cmd->flag, 0, 0, 0, 0, "Enable (local) Z axis deformation");
+ }
+ uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:", lx,(cy-=19),buttonWidth, 19, &cmd->fac, -10.0, 10.0, 5, 0, "Define the amount of deformation");
+ uiDefButF(block, NUM, B_MODIFIER_RECALC, "Radius:", lx,(cy-=19),buttonWidth, 19, &cmd->radius, 0.0, 100.0, 10.0, 0, "Only deform vertices within this distance from the center of the effect (leave as 0 for infinite)");
+ uiDefButF(block, NUM, B_MODIFIER_RECALC, "Size:", lx,(cy-=19),buttonWidth, 19, &cmd->size, 0.0, 100.0, 10.0, 0, "Size of projection shape (leave as 0 for auto)");
+ uiDefButBitS(block, TOG, MOD_CAST_SIZE_FROM_RADIUS, B_MODIFIER_RECALC, "From radius", lx+buttonWidth,cy,80,19, &cmd->flag, 0, 0, 0, 0, "Use radius as size of projection shape (0 = auto)");
+ if (ob->type == OB_MESH) {
+ but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &cmd->defgrp_name, 0.0, 31.0, 0, 0, "Vertex Group name to define which vertices are affected");
+ }
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx,(cy-=19), buttonWidth,19, &cmd->object, "Control object: if available, its location determines the center of the effect");
+ if(cmd->object) {
+ uiDefButBitS(block, TOG, MOD_CAST_USE_OB_TRANSFORM, B_MODIFIER_RECALC, "Use transform", lx+buttonWidth,cy,80,19, &cmd->flag, 0, 0, 0, 0, "Use object transform to control projection shape");
+ }
} else if (md->type==eModifierType_Wave) {
WaveModifierData *wmd = (WaveModifierData*) md;
uiDefButBitS(block, TOG, WAV_X, B_MODIFIER_RECALC, "X", lx,(cy-=19),45,19, &wmd->flag, 0, 0, 0, 0, "Enable X axis motion");