1010
/* add start and end caps */
1012
float startoffset[4][4];
1018
int capVerts, capEdges, capFaces;
1020
capVerts = start_cap->getNumVerts(start_cap);
1021
capEdges = start_cap->getNumEdges(start_cap);
1022
capFaces = start_cap->getNumFaces(start_cap);
1023
cap_mvert = start_cap->getVertArray(start_cap);
1024
cap_medge = start_cap->getEdgeArray(start_cap);
1025
cap_mface = start_cap->getFaceArray(start_cap);
1027
Mat4Invert(startoffset, offset);
1029
vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
1030
"arrayModifier_doArray vert_map");
1032
origindex = result->getVertDataArray(result, CD_ORIGINDEX);
1033
for(i = 0; i < capVerts; i++) {
1034
MVert *mv = &cap_mvert[i];
1037
if(amd->flags & MOD_ARR_MERGE) {
1042
VECCOPY(tmp_co, mv->co);
1043
Mat4MulVecfl(startoffset, tmp_co);
1045
for(j = 0; j < maxVerts; j++) {
1046
in_mv = &src_mvert[j];
1047
/* if this vert is within merge limit, merge */
1048
if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) {
1049
vert_map[i] = calc_mapping(indexMap, j, 0);
1057
DM_copy_vert_data(start_cap, result, i, numVerts, 1);
1058
mvert[numVerts] = *mv;
1059
Mat4MulVecfl(startoffset, mvert[numVerts].co);
1060
origindex[numVerts] = ORIGINDEX_NONE;
1062
vert_map[i] = numVerts;
1067
origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
1068
for(i = 0; i < capEdges; i++) {
1071
v1 = vert_map[cap_medge[i].v1];
1072
v2 = vert_map[cap_medge[i].v2];
1074
if(!BLI_edgehash_haskey(edges, v1, v2)) {
1075
DM_copy_edge_data(start_cap, result, i, numEdges, 1);
1076
medge[numEdges] = cap_medge[i];
1077
medge[numEdges].v1 = v1;
1078
medge[numEdges].v2 = v2;
1079
origindex[numEdges] = ORIGINDEX_NONE;
1084
origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
1085
for(i = 0; i < capFaces; i++) {
1086
DM_copy_face_data(start_cap, result, i, numFaces, 1);
1087
mface[numFaces] = cap_mface[i];
1088
mface[numFaces].v1 = vert_map[mface[numFaces].v1];
1089
mface[numFaces].v2 = vert_map[mface[numFaces].v2];
1090
mface[numFaces].v3 = vert_map[mface[numFaces].v3];
1091
if(mface[numFaces].v4)
1092
mface[numFaces].v4 = vert_map[mface[numFaces].v4];
1093
origindex[numFaces] = ORIGINDEX_NONE;
1098
MEM_freeN(vert_map);
1099
start_cap->release(start_cap);
1103
float endoffset[4][4];
1109
int capVerts, capEdges, capFaces;
1111
capVerts = end_cap->getNumVerts(end_cap);
1112
capEdges = end_cap->getNumEdges(end_cap);
1113
capFaces = end_cap->getNumFaces(end_cap);
1114
cap_mvert = end_cap->getVertArray(end_cap);
1115
cap_medge = end_cap->getEdgeArray(end_cap);
1116
cap_mface = end_cap->getFaceArray(end_cap);
1118
Mat4MulMat4(endoffset, final_offset, offset);
1120
vert_map = MEM_callocN(sizeof(*vert_map) * capVerts,
1121
"arrayModifier_doArray vert_map");
1123
origindex = result->getVertDataArray(result, CD_ORIGINDEX);
1124
for(i = 0; i < capVerts; i++) {
1125
MVert *mv = &cap_mvert[i];
1128
if(amd->flags & MOD_ARR_MERGE) {
1133
VECCOPY(tmp_co, mv->co);
1134
Mat4MulVecfl(offset, tmp_co);
1136
for(j = 0; j < maxVerts; j++) {
1137
in_mv = &src_mvert[j];
1138
/* if this vert is within merge limit, merge */
1139
if(VecLenCompare(tmp_co, in_mv->co, amd->merge_dist)) {
1140
vert_map[i] = calc_mapping(indexMap, j, count - 1);
1148
DM_copy_vert_data(end_cap, result, i, numVerts, 1);
1149
mvert[numVerts] = *mv;
1150
Mat4MulVecfl(endoffset, mvert[numVerts].co);
1151
origindex[numVerts] = ORIGINDEX_NONE;
1153
vert_map[i] = numVerts;
1158
origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
1159
for(i = 0; i < capEdges; i++) {
1162
v1 = vert_map[cap_medge[i].v1];
1163
v2 = vert_map[cap_medge[i].v2];
1165
if(!BLI_edgehash_haskey(edges, v1, v2)) {
1166
DM_copy_edge_data(end_cap, result, i, numEdges, 1);
1167
medge[numEdges] = cap_medge[i];
1168
medge[numEdges].v1 = v1;
1169
medge[numEdges].v2 = v2;
1170
origindex[numEdges] = ORIGINDEX_NONE;
1175
origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
1176
for(i = 0; i < capFaces; i++) {
1177
DM_copy_face_data(end_cap, result, i, numFaces, 1);
1178
mface[numFaces] = cap_mface[i];
1179
mface[numFaces].v1 = vert_map[mface[numFaces].v1];
1180
mface[numFaces].v2 = vert_map[mface[numFaces].v2];
1181
mface[numFaces].v3 = vert_map[mface[numFaces].v3];
1182
if(mface[numFaces].v4)
1183
mface[numFaces].v4 = vert_map[mface[numFaces].v4];
1184
origindex[numFaces] = ORIGINDEX_NONE;
1189
MEM_freeN(vert_map);
1190
end_cap->release(end_cap);
1193
BLI_edgehash_free(edges, NULL);
986
1194
MEM_freeN(indexMap);
988
1196
CDDM_lower_num_verts(result, numVerts);
1297
1485
int newIndex; /* the index of the new DerivedMesh face */
1300
static void smoothface_free(void *face)
1305
static SmoothMesh *smoothmesh_new()
1488
typedef struct SmoothMesh {
1492
int num_verts, num_edges, num_faces;
1493
int max_verts, max_edges, max_faces;
1495
float threshold; /* the cosine of the smoothing angle */
1499
static SmoothVert *smoothvert_copy(SmoothVert *vert, SmoothMesh *mesh)
1501
SmoothVert *copy = &mesh->verts[mesh->num_verts];
1503
if(mesh->num_verts >= mesh->max_verts) {
1504
printf("Attempted to add a SmoothMesh vert beyond end of array\n");
1510
copy->newIndex = mesh->num_verts;
1513
#ifdef EDGESPLIT_DEBUG_2
1514
printf("copied vert %4d to vert %4d\n", vert->newIndex, copy->newIndex);
1519
static SmoothEdge *smoothedge_copy(SmoothEdge *edge, SmoothMesh *mesh)
1521
SmoothEdge *copy = &mesh->edges[mesh->num_edges];
1523
if(mesh->num_edges >= mesh->max_edges) {
1524
printf("Attempted to add a SmoothMesh edge beyond end of array\n");
1530
copy->newIndex = mesh->num_edges;
1533
#ifdef EDGESPLIT_DEBUG_2
1534
printf("copied edge %4d to edge %4d\n", edge->newIndex, copy->newIndex);
1539
static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
1542
for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
1543
if(edge->verts[i] == vert) return 1;
1548
static SmoothMesh *smoothmesh_new(int num_verts, int num_edges, int num_faces,
1549
int max_verts, int max_edges, int max_faces)
1307
1551
SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
1308
mesh->verts = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
1309
mesh->edges = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
1310
mesh->faces = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
1552
mesh->verts = MEM_callocN(sizeof(*mesh->verts) * max_verts,
1553
"SmoothMesh.verts");
1554
mesh->edges = MEM_callocN(sizeof(*mesh->edges) * max_edges,
1555
"SmoothMesh.edges");
1556
mesh->faces = MEM_callocN(sizeof(*mesh->faces) * max_faces,
1557
"SmoothMesh.faces");
1559
mesh->num_verts = num_verts;
1560
mesh->num_edges = num_edges;
1561
mesh->num_faces = num_faces;
1563
mesh->max_verts = max_verts;
1564
mesh->max_edges = max_edges;
1565
mesh->max_faces = max_faces;
1315
1570
static void smoothmesh_free(SmoothMesh *mesh)
1317
BLI_ghash_free(mesh->verts, NULL, smoothvert_free);
1318
BLI_ghash_free(mesh->edges, NULL, smoothedge_free);
1319
BLI_ghash_free(mesh->faces, NULL, smoothface_free);
1574
for(i = 0; i < mesh->num_verts; ++i)
1575
BLI_linklist_free(mesh->verts[i].faces, NULL);
1577
for(i = 0; i < mesh->num_edges; ++i)
1578
BLI_linklist_free(mesh->edges[i].faces, NULL);
1580
MEM_freeN(mesh->verts);
1581
MEM_freeN(mesh->edges);
1582
MEM_freeN(mesh->faces);
1320
1583
MEM_freeN(mesh);
1586
static void smoothmesh_resize_verts(SmoothMesh *mesh, int max_verts)
1591
if(max_verts <= mesh->max_verts) return;
1593
tmp = MEM_callocN(sizeof(*tmp) * max_verts, "SmoothMesh.verts");
1595
memcpy(tmp, mesh->verts, sizeof(*tmp) * mesh->num_verts);
1597
/* remap vert pointers in edges */
1598
for(i = 0; i < mesh->num_edges; ++i) {
1600
SmoothEdge *edge = &mesh->edges[i];
1602
for(j = 0; j < SMOOTHEDGE_NUM_VERTS; ++j)
1603
/* pointer arithmetic to get vert array index */
1604
edge->verts[j] = &tmp[edge->verts[j] - mesh->verts];
1607
MEM_freeN(mesh->verts);
1609
mesh->max_verts = max_verts;
1612
static void smoothmesh_resize_edges(SmoothMesh *mesh, int max_edges)
1617
if(max_edges <= mesh->max_edges) return;
1619
tmp = MEM_callocN(sizeof(*tmp) * max_edges, "SmoothMesh.edges");
1621
memcpy(tmp, mesh->edges, sizeof(*tmp) * mesh->num_edges);
1623
/* remap edge pointers in faces */
1624
for(i = 0; i < mesh->num_faces; ++i) {
1626
SmoothFace *face = &mesh->faces[i];
1628
for(j = 0; j < SMOOTHFACE_MAX_EDGES; ++j)
1630
/* pointer arithmetic to get edge array index */
1631
face->edges[j] = &tmp[face->edges[j] - mesh->edges];
1634
MEM_freeN(mesh->edges);
1636
mesh->max_edges = max_edges;
1323
1639
#ifdef EDGESPLIT_DEBUG_0
1324
1640
static void smoothmesh_print(SmoothMesh *mesh)
3324
static void smoothModifier_initData(ModifierData *md)
3326
SmoothModifierData *smd = (SmoothModifierData*) md;
3330
smd->flag = MOD_SMOOTH_X | MOD_SMOOTH_Y | MOD_SMOOTH_Z;
3331
smd->defgrp_name[0] = '\0';
3334
static void smoothModifier_copyData(ModifierData *md, ModifierData *target)
3336
SmoothModifierData *smd = (SmoothModifierData*) md;
3337
SmoothModifierData *tsmd = (SmoothModifierData*) target;
3339
tsmd->fac = smd->fac;
3340
tsmd->repeat = smd->repeat;
3341
tsmd->flag = smd->flag;
3342
strncpy(tsmd->defgrp_name, smd->defgrp_name, 32);
3345
int smoothModifier_isDisabled(ModifierData *md)
3347
SmoothModifierData *smd = (SmoothModifierData*) md;
3350
flag = smd->flag & (MOD_SMOOTH_X|MOD_SMOOTH_Y|MOD_SMOOTH_Z);
3352
/* disable if modifier is off for X, Y and Z or if factor is 0 */
3353
if((smd->fac == 0.0f) || flag == 0) return 1;
3358
CustomDataMask smoothModifier_requiredDataMask(ModifierData *md)
3360
SmoothModifierData *smd = (SmoothModifierData *)md;
3361
CustomDataMask dataMask = 0;
3363
/* ask for vertexgroups if we need them */
3364
if(smd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
3369
static void smoothModifier_do(
3370
SmoothModifierData *smd, Object *ob, DerivedMesh *dm,
3371
float (*vertexCos)[3], int numVerts)
3373
MDeformVert *dvert = NULL;
3374
MEdge *medges = NULL;
3376
int i, j, numDMEdges, defgrp_index;
3377
unsigned char *uctmp;
3378
float *ftmp, fac, facm;
3380
ftmp = (float*)MEM_callocN(3*sizeof(float)*numVerts,
3381
"smoothmodifier_f");
3383
uctmp = (unsigned char*)MEM_callocN(sizeof(unsigned char)*numVerts,
3384
"smoothmodifier_uc");
3386
if (ftmp) MEM_freeN(ftmp);
3393
medges = CDDM_get_edges(dm);
3394
numDMEdges = dm->getNumEdges(dm);
3398
if (smd->defgrp_name[0]) {
3401
for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
3402
if (!strcmp(def->name, smd->defgrp_name)) {
3409
if (defgrp_index >= 0)
3410
dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
3412
/* NOTICE: this can be optimized a little bit by moving the
3413
* if (dvert) out of the loop, if needed */
3414
for (j = 0; j < smd->repeat; j++) {
3415
for (i = 0; i < numDMEdges; i++) {
3418
unsigned int idx1, idx2;
3420
idx1 = medges[i].v1;
3421
idx2 = medges[i].v2;
3423
v1 = vertexCos[idx1];
3424
v2 = vertexCos[idx2];
3426
fvec[0] = (v1[0] + v2[0]) / 2.0;
3427
fvec[1] = (v1[1] + v2[1]) / 2.0;
3428
fvec[2] = (v1[2] + v2[2]) / 2.0;
3433
if (uctmp[idx1] < 255) {
3435
VecAddf(v1, v1, fvec);
3437
if (uctmp[idx2] < 255) {
3439
VecAddf(v2, v2, fvec);
3444
for (i = 0; i < numVerts; i++) {
3445
MDeformWeight *dw = NULL;
3446
float f, fm, facw, *fp, *v;
3448
short flag = smd->flag;
3453
for (k = 0; k < dvert[i].totweight; ++k) {
3454
if(dvert[i].dw[k].def_nr == defgrp_index) {
3455
dw = &dvert[i].dw[k];
3461
f = fac * dw->weight;
3464
/* fp is the sum of uctmp[i] verts, so must be averaged */
3467
facw = f / (float)uctmp[i];
3469
if (flag & MOD_SMOOTH_X)
3470
v[0] = fm * v[0] + facw * fp[0];
3471
if (flag & MOD_SMOOTH_Y)
3472
v[1] = fm * v[1] + facw * fp[1];
3473
if (flag & MOD_SMOOTH_Z)
3474
v[2] = fm * v[2] + facw * fp[2];
3477
else { /* no vertex group */
3478
for (i = 0; i < numVerts; i++) {
3479
float facw, *fp, *v;
3480
short flag = smd->flag;
3485
/* fp is the sum of uctmp[i] verts, so must be averaged */
3488
facw = fac / (float)uctmp[i];
3490
if (flag & MOD_SMOOTH_X)
3491
v[0] = facm * v[0] + facw * fp[0];
3492
if (flag & MOD_SMOOTH_Y)
3493
v[1] = facm * v[1] + facw * fp[1];
3494
if (flag & MOD_SMOOTH_Z)
3495
v[2] = facm * v[2] + facw * fp[2];
3500
memset(ftmp, 0, 3*sizeof(float)*numVerts);
3501
memset(uctmp, 0, sizeof(unsigned char)*numVerts);
3508
static void smoothModifier_deformVerts(
3509
ModifierData *md, Object *ob, DerivedMesh *derivedData,
3510
float (*vertexCos)[3], int numVerts)
3514
if(derivedData) dm = CDDM_copy(derivedData);
3515
else dm = CDDM_from_mesh(ob->data, ob);
3517
CDDM_apply_vert_coords(dm, vertexCos);
3518
CDDM_calc_normals(dm);
3520
smoothModifier_do((SmoothModifierData *)md, ob, dm,
3521
vertexCos, numVerts);
3526
static void smoothModifier_deformVertsEM(
3527
ModifierData *md, Object *ob, EditMesh *editData,
3528
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
3532
if(derivedData) dm = CDDM_copy(derivedData);
3533
else dm = CDDM_from_editmesh(editData, ob->data);
3535
CDDM_apply_vert_coords(dm, vertexCos);
3536
CDDM_calc_normals(dm);
3538
smoothModifier_do((SmoothModifierData *)md, ob, dm,
3539
vertexCos, numVerts);
3546
static void castModifier_initData(ModifierData *md)
3548
CastModifierData *cmd = (CastModifierData*) md;
3553
cmd->flag = MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z
3554
| MOD_CAST_SIZE_FROM_RADIUS;
3555
cmd->type = MOD_CAST_TYPE_SPHERE;
3556
cmd->defgrp_name[0] = '\0';
3561
static void castModifier_copyData(ModifierData *md, ModifierData *target)
3563
CastModifierData *cmd = (CastModifierData*) md;
3564
CastModifierData *tcmd = (CastModifierData*) target;
3566
tcmd->fac = cmd->fac;
3567
tcmd->radius = cmd->radius;
3568
tcmd->size = cmd->size;
3569
tcmd->flag = cmd->flag;
3570
tcmd->type = cmd->type;
3571
tcmd->object = cmd->object;
3572
strncpy(tcmd->defgrp_name, cmd->defgrp_name, 32);
3575
int castModifier_isDisabled(ModifierData *md)
3577
CastModifierData *cmd = (CastModifierData*) md;
3580
flag = cmd->flag & (MOD_CAST_X|MOD_CAST_Y|MOD_CAST_Z);
3582
if((cmd->fac == 0.0f) || flag == 0) return 1;
3587
CustomDataMask castModifier_requiredDataMask(ModifierData *md)
3589
CastModifierData *cmd = (CastModifierData *)md;
3590
CustomDataMask dataMask = 0;
3592
/* ask for vertexgroups if we need them */
3593
if(cmd->defgrp_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
3598
static void castModifier_foreachObjectLink(
3599
ModifierData *md, Object *ob,
3600
void (*walk)(void *userData, Object *ob, Object **obpoin),
3603
CastModifierData *cmd = (CastModifierData*) md;
3605
walk (userData, ob, &cmd->object);
3608
static void castModifier_updateDepgraph(
3609
ModifierData *md, DagForest *forest, Object *ob,
3612
CastModifierData *cmd = (CastModifierData*) md;
3615
DagNode *curNode = dag_get_node(forest, cmd->object);
3617
dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA);
3621
static void castModifier_sphere_do(
3622
CastModifierData *cmd, Object *ob, DerivedMesh *dm,
3623
float (*vertexCos)[3], int numVerts)
3625
MDeformVert *dvert = NULL;
3627
Object *ctrl_ob = NULL;
3629
int i, defgrp_index = -1;
3632
float fac, facm, len = 0.0f;
3633
float vec[3], center[3] = {0.0f, 0.0f, 0.0f};
3634
float mat[4][4], imat[4][4];
3640
type = cmd->type; /* projection type: sphere or cylinder */
3642
if (type == MOD_CAST_TYPE_CYLINDER)
3643
flag &= ~MOD_CAST_Z;
3645
ctrl_ob = cmd->object;
3647
/* spherify's center is {0, 0, 0} (the ob's own center in its local
3648
* space), by default, but if the user defined a control object,
3649
* we use its location, transformed to ob's local space */
3651
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3652
Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat);
3653
Mat4MulMat4(mat, ob->obmat, ctrl_ob->imat);
3654
Mat4Invert(imat, mat);
3657
Mat4Invert(ob->imat, ob->obmat);
3658
VECCOPY(center, ctrl_ob->obmat[3]);
3659
Mat4MulVecfl(ob->imat, center);
3662
/* now we check which options the user wants */
3664
/* 1) (flag was checked in the "if (ctrl_ob)" block above) */
3665
/* 2) cmd->radius > 0.0f: only the vertices within this radius from
3666
* the center of the effect should be deformed */
3667
if (cmd->radius > FLT_EPSILON) has_radius = 1;
3669
/* 3) if we were given a vertex group name,
3670
* only those vertices should be affected */
3671
if (cmd->defgrp_name[0]) {
3674
for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
3675
if (!strcmp(def->name, cmd->defgrp_name)) {
3682
if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
3683
dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
3685
if(flag & MOD_CAST_SIZE_FROM_RADIUS) {
3693
for (i = 0; i < numVerts; i++) {
3694
len += VecLenf(center, vertexCos[i]);
3698
if (len == 0.0f) len = 10.0f;
3701
/* ready to apply the effect, one vertex at a time;
3702
* tiny optimization: the code is separated (with parts repeated)
3703
* in two possible cases:
3704
* with or w/o a vgroup. With lots of if's in the code below,
3705
* further optimizations are possible, if needed */
3706
if (dvert) { /* with a vgroup */
3707
float fac_orig = fac;
3708
for (i = 0; i < numVerts; i++) {
3709
MDeformWeight *dw = NULL;
3713
VECCOPY(tmp_co, vertexCos[i]);
3715
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3716
Mat4MulVecfl(mat, tmp_co);
3718
VecSubf(tmp_co, tmp_co, center);
3722
VECCOPY(vec, tmp_co);
3724
if (type == MOD_CAST_TYPE_CYLINDER)
3728
if (VecLength(vec) > cmd->radius) continue;
3731
for (j = 0; j < dvert[i].totweight; ++j) {
3732
if(dvert[i].dw[j].def_nr == defgrp_index) {
3733
dw = &dvert[i].dw[j];
3739
fac = fac_orig * dw->weight;
3744
if (flag & MOD_CAST_X)
3745
tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
3746
if (flag & MOD_CAST_Y)
3747
tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
3748
if (flag & MOD_CAST_Z)
3749
tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
3752
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3753
Mat4MulVecfl(imat, tmp_co);
3755
VecAddf(tmp_co, tmp_co, center);
3759
VECCOPY(vertexCos[i], tmp_co);
3765
for (i = 0; i < numVerts; i++) {
3768
VECCOPY(tmp_co, vertexCos[i]);
3770
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3771
Mat4MulVecfl(mat, tmp_co);
3773
VecSubf(tmp_co, tmp_co, center);
3777
VECCOPY(vec, tmp_co);
3779
if (type == MOD_CAST_TYPE_CYLINDER)
3783
if (VecLength(vec) > cmd->radius) continue;
3788
if (flag & MOD_CAST_X)
3789
tmp_co[0] = fac*vec[0]*len + facm*tmp_co[0];
3790
if (flag & MOD_CAST_Y)
3791
tmp_co[1] = fac*vec[1]*len + facm*tmp_co[1];
3792
if (flag & MOD_CAST_Z)
3793
tmp_co[2] = fac*vec[2]*len + facm*tmp_co[2];
3796
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3797
Mat4MulVecfl(imat, tmp_co);
3799
VecAddf(tmp_co, tmp_co, center);
3803
VECCOPY(vertexCos[i], tmp_co);
3807
static void castModifier_cuboid_do(
3808
CastModifierData *cmd, Object *ob, DerivedMesh *dm,
3809
float (*vertexCos)[3], int numVerts)
3811
MDeformVert *dvert = NULL;
3812
Object *ctrl_ob = NULL;
3814
int i, defgrp_index = -1;
3818
float min[3], max[3], bb[8][3];
3819
float center[3] = {0.0f, 0.0f, 0.0f};
3820
float mat[4][4], imat[4][4];
3827
ctrl_ob = cmd->object;
3829
/* now we check which options the user wants */
3831
/* 1) (flag was checked in the "if (ctrl_ob)" block above) */
3832
/* 2) cmd->radius > 0.0f: only the vertices within this radius from
3833
* the center of the effect should be deformed */
3834
if (cmd->radius > FLT_EPSILON) has_radius = 1;
3836
/* 3) if we were given a vertex group name,
3837
* only those vertices should be affected */
3838
if (cmd->defgrp_name[0]) {
3841
for (i = 0, def = ob->defbase.first; def; def = def->next, i++) {
3842
if (!strcmp(def->name, cmd->defgrp_name)) {
3849
if ((ob->type == OB_MESH) && dm && defgrp_index >= 0)
3850
dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
3853
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3854
Mat4Invert(ctrl_ob->imat, ctrl_ob->obmat);
3855
Mat4MulMat4(mat, ob->obmat, ctrl_ob->imat);
3856
Mat4Invert(imat, mat);
3859
Mat4Invert(ob->imat, ob->obmat);
3860
VECCOPY(center, ctrl_ob->obmat[3]);
3861
Mat4MulVecfl(ob->imat, center);
3864
if((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
3865
for(i = 0; i < 3; i++) {
3866
min[i] = -cmd->radius;
3867
max[i] = cmd->radius;
3869
} else if(!(flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
3870
for(i = 0; i < 3; i++) {
3871
min[i] = -cmd->size;
3876
/* We can't use the object's bound box because other modifiers
3877
* may have changed the vertex data. */
3878
INIT_MINMAX(min, max);
3880
/* Cast's center is the ob's own center in its local space,
3881
* by default, but if the user defined a control object, we use
3882
* its location, transformed to ob's local space. */
3886
/* let the center of the ctrl_ob be part of the bound box: */
3887
DO_MINMAX(center, min, max);
3889
for (i = 0; i < numVerts; i++) {
3890
VecSubf(vec, vertexCos[i], center);
3891
DO_MINMAX(vec, min, max);
3895
for (i = 0; i < numVerts; i++) {
3896
DO_MINMAX(vertexCos[i], min, max);
3900
/* we want a symmetric bound box around the origin */
3901
if (fabs(min[0]) > fabs(max[0])) max[0] = fabs(min[0]);
3902
if (fabs(min[1]) > fabs(max[1])) max[1] = fabs(min[1]);
3903
if (fabs(min[2]) > fabs(max[2])) max[2] = fabs(min[2]);
3909
/* building our custom bounding box */
3910
bb[0][0] = bb[2][0] = bb[4][0] = bb[6][0] = min[0];
3911
bb[1][0] = bb[3][0] = bb[5][0] = bb[7][0] = max[0];
3912
bb[0][1] = bb[1][1] = bb[4][1] = bb[5][1] = min[1];
3913
bb[2][1] = bb[3][1] = bb[6][1] = bb[7][1] = max[1];
3914
bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
3915
bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];
3917
/* ready to apply the effect, one vertex at a time;
3918
* tiny optimization: the code is separated (with parts repeated)
3919
* in two possible cases:
3920
* with or w/o a vgroup. With lots of if's in the code below,
3921
* further optimizations are possible, if needed */
3922
if (dvert) { /* with a vgroup */
3923
float fac_orig = fac;
3924
for (i = 0; i < numVerts; i++) {
3925
MDeformWeight *dw = NULL;
3926
int j, octant, coord;
3927
float d[3], dmax, apex[3], fbb;
3930
VECCOPY(tmp_co, vertexCos[i]);
3932
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
3933
Mat4MulVecfl(mat, tmp_co);
3935
VecSubf(tmp_co, tmp_co, center);
3940
if (fabs(tmp_co[0]) > cmd->radius ||
3941
fabs(tmp_co[1]) > cmd->radius ||
3942
fabs(tmp_co[2]) > cmd->radius) continue;
3945
for (j = 0; j < dvert[i].totweight; ++j) {
3946
if(dvert[i].dw[j].def_nr == defgrp_index) {
3947
dw = &dvert[i].dw[j];
3953
fac = fac_orig * dw->weight;
3956
/* The algo used to project the vertices to their
3957
* bounding box (bb) is pretty simple:
3958
* for each vertex v:
3959
* 1) find in which octant v is in;
3960
* 2) find which outer "wall" of that octant is closer to v;
3961
* 3) calculate factor (var fbb) to project v to that wall;
3964
/* find in which octant this vertex is in */
3966
if (tmp_co[0] > 0.0f) octant += 1;
3967
if (tmp_co[1] > 0.0f) octant += 2;
3968
if (tmp_co[2] > 0.0f) octant += 4;
3970
/* apex is the bb's vertex at the chosen octant */
3971
VecCopyf(apex, bb[octant]);
3973
/* find which bb plane is closest to this vertex ... */
3974
d[0] = tmp_co[0] / apex[0];
3975
d[1] = tmp_co[1] / apex[1];
3976
d[2] = tmp_co[2] / apex[2];
3978
/* ... (the closest has the higher (closer to 1) d value) */
3986
/* dmax = d[2]; */ /* commented, we don't need it */
3990
/* ok, now we know which coordinate of the vertex to use */
3992
if (fabs(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
3995
/* finally, this is the factor we wanted, to project the vertex
3996
* to its bounding box (bb) */
3997
fbb = apex[coord] / tmp_co[coord];
3999
/* calculate the new vertex position */
4000
if (flag & MOD_CAST_X)
4001
tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
4002
if (flag & MOD_CAST_Y)
4003
tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
4004
if (flag & MOD_CAST_Z)
4005
tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
4008
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
4009
Mat4MulVecfl(imat, tmp_co);
4011
VecAddf(tmp_co, tmp_co, center);
4015
VECCOPY(vertexCos[i], tmp_co);
4020
/* no vgroup (check previous case for comments about the code) */
4021
for (i = 0; i < numVerts; i++) {
4023
float d[3], dmax, fbb, apex[3];
4026
VECCOPY(tmp_co, vertexCos[i]);
4028
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
4029
Mat4MulVecfl(mat, tmp_co);
4031
VecSubf(tmp_co, tmp_co, center);
4036
if (fabs(tmp_co[0]) > cmd->radius ||
4037
fabs(tmp_co[1]) > cmd->radius ||
4038
fabs(tmp_co[2]) > cmd->radius) continue;
4042
if (tmp_co[0] > 0.0f) octant += 1;
4043
if (tmp_co[1] > 0.0f) octant += 2;
4044
if (tmp_co[2] > 0.0f) octant += 4;
4046
VecCopyf(apex, bb[octant]);
4048
d[0] = tmp_co[0] / apex[0];
4049
d[1] = tmp_co[1] / apex[1];
4050
d[2] = tmp_co[2] / apex[2];
4059
/* dmax = d[2]; */ /* commented, we don't need it */
4063
if (fabs(tmp_co[coord]) < FLT_EPSILON)
4066
fbb = apex[coord] / tmp_co[coord];
4068
if (flag & MOD_CAST_X)
4069
tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
4070
if (flag & MOD_CAST_Y)
4071
tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
4072
if (flag & MOD_CAST_Z)
4073
tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
4076
if(flag & MOD_CAST_USE_OB_TRANSFORM) {
4077
Mat4MulVecfl(imat, tmp_co);
4079
VecAddf(tmp_co, tmp_co, center);
4083
VECCOPY(vertexCos[i], tmp_co);
4087
static void castModifier_deformVerts(
4088
ModifierData *md, Object *ob, DerivedMesh *derivedData,
4089
float (*vertexCos)[3], int numVerts)
4091
DerivedMesh *dm = derivedData;
4092
CastModifierData *cmd = (CastModifierData *)md;
4094
if (!dm && ob->type == OB_MESH)
4095
dm = CDDM_from_mesh(ob->data, ob);
4097
if (cmd->type == MOD_CAST_TYPE_CUBOID) {
4098
castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
4099
} else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
4100
castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
4103
if (!derivedData && dm) dm->release(dm);
4106
static void castModifier_deformVertsEM(
4107
ModifierData *md, Object *ob, EditMesh *editData,
4108
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
4110
DerivedMesh *dm = derivedData;
4111
CastModifierData *cmd = (CastModifierData *)md;
4113
if (!dm && ob->type == OB_MESH)
4114
dm = CDDM_from_editmesh(editData, ob->data);
4116
if (cmd->type == MOD_CAST_TYPE_CUBOID) {
4117
castModifier_cuboid_do(cmd, ob, dm, vertexCos, numVerts);
4118
} else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
4119
castModifier_sphere_do(cmd, ob, dm, vertexCos, numVerts);
4122
if (!derivedData && dm) dm->release(dm);
2970
4127
static void waveModifier_initData(ModifierData *md)
2972
4129
WaveModifierData *wmd = (WaveModifierData*) md; // whadya know, moved here from Iraq
2974
wmd->flag |= (WAV_X+WAV_Y+WAV_CYCL);
4131
wmd->flag |= (MOD_WAVE_X | MOD_WAVE_Y | MOD_WAVE_CYCL
4132
| MOD_WAVE_NORM_X | MOD_WAVE_NORM_Y | MOD_WAVE_NORM_Z);
2976
4134
wmd->objectcenter = NULL;
4135
wmd->texture = NULL;
4136
wmd->map_object = NULL;
2977
4137
wmd->height= 0.5f;
2978
4138
wmd->width= 1.5f;
2979
4139
wmd->speed= 0.5f;
2980
4140
wmd->narrow= 1.5f;
2981
4141
wmd->lifetime= 0.0f;
2982
4142
wmd->damp= 10.0f;
4143
wmd->texmapping = MOD_WAV_MAP_LOCAL;
4144
wmd->defgrp_name[0] = 0;
2985
4147
static void waveModifier_copyData(ModifierData *md, ModifierData *target)