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!
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user