diff options
-rw-r--r-- | source/blender/blenkernel/BKE_modifier.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 239 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 8 | ||||
-rw-r--r-- | source/blender/src/buttons_object.c | 6 |
5 files changed, 244 insertions, 15 deletions
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 9e10e77dfe7..b0736a1ab72 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -76,7 +76,7 @@ typedef struct ModifierTypeInfo { * tested by the system, this is just if the data validates (for example, a * lattice will return false if the lattice object is not defined). * - * This function must be present. + * This function is optional (assumes never disabled if not present). */ int (*isDisabled)(struct ModifierData *md); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 6ad09edee43..b5a22913be6 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1022,7 +1022,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM ModifierTypeInfo *mti = modifierType_get_info(md->type); if (!(md->mode&(1<<useRenderParams))) continue; - if (mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md)) continue; if (mti->type==eModifierTypeType_OnlyDeform) { mti->deformVerts(md, ob, deformedVerts, numVerts); @@ -1049,7 +1049,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM if (!(md->mode&(1<<useRenderParams))) continue; if (mti->type==eModifierTypeType_OnlyDeform && !useDeform) continue; - if (mti->isDisabled(md)) continue; + if (mti->isDisabled && mti->isDisabled(md)) continue; /* How to apply modifier depends on (a) what we already have as * a result of previous modifiers (could be a DerivedMesh or just diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 49c6c5186b2..709d6f0cd40 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -118,11 +118,6 @@ static ModifierData *subsurfModifier_allocData(void) return (ModifierData*) smd; } -static int subsurfModifier_isDisabled(ModifierData *md) -{ - return 0; -} - static void *subsurfModifier_applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int useRenderParams) { SubsurfModifierData *smd = (SubsurfModifierData*) md; @@ -163,11 +158,6 @@ static ModifierData *buildModifier_allocData(void) return (ModifierData*) bmd; } -static int buildModifier_isDisabled(ModifierData *md) -{ - return 0; -} - static int buildModifier_dependsOnTime(ModifierData *md) { return 1; @@ -381,6 +371,225 @@ static void *buildModifier_applyModifier(ModifierData *md, Object *ob, DerivedMe return derivedmesh_from_displistmesh(ndlm); } +/* Mirror */ + +static ModifierData *mirrorModifier_allocData(void) +{ + MirrorModifierData *mmd = allocModifierData(eModifierType_Mirror, sizeof(MirrorModifierData)); + + mmd->axis = 0; + mmd->tolerance = 0.001; + + return (ModifierData*) mmd; +} + +static void *mirrorModifier_applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int useRenderParams) +{ + MirrorModifierData *mmd = (MirrorModifierData*) md; + DispListMesh *dlm=NULL, *ndlm = MEM_callocN(sizeof(*dlm), "mm_dlm"); + MVert *mvert; + MEdge *medge; + MFace *mface; + TFace *tface; + MCol *mcol; + int i, j, totvert, totedge, totface; + int axis = mmd->axis; + float tolerance = mmd->tolerance; + + if (dm) { + dlm = dm->convertToDispListMesh(dm); + + mvert = dlm->mvert; + medge = dlm->medge; + mface = dlm->mface; + tface = dlm->tface; + mcol = dlm->mcol; + totvert = dlm->totvert; + totedge = dlm->totedge; + totface = dlm->totface; + } else { + Mesh *me = ob->data; + + mvert = me->mvert; + medge = me->medge; + mface = me->mface; + tface = me->tface; + mcol = me->mcol; + totvert = me->totvert; + totedge = me->totedge; + totface = me->totface; + } + + ndlm->mvert = MEM_mallocN(sizeof(*mvert)*totvert*2, "mm_mv"); + for (i=0,j=totvert; i<totvert; i++) { + MVert *mv = &mvert[i]; + MVert *nmv = &ndlm->mvert[i]; + + memcpy(nmv, mv, sizeof(*mv)); + + if (ABS(nmv->co[axis])<=tolerance) { + nmv->co[axis] = 0; + *((int*) nmv->no) = i; + } else { + MVert *nmvMirror = &ndlm->mvert[j]; + + /* Because the topology result (# of vertices) must stuff the same + * if the mesh data is overridden by vertex cos, have to calc sharedness + * based on original coordinates. Only write new cos for non-shared + * vertices. + */ + if (vertexCos) { + VECCOPY(nmv->co, vertexCos[i]); + } + + memcpy(nmvMirror, nmv, sizeof(*mv)); + nmvMirror->co[axis] = -nmvMirror->co[axis]; + + *((int*) nmv->no) = j++; + } + } + ndlm->totvert = j; + + if (medge) { + ndlm->medge = MEM_mallocN(sizeof(*medge)*totedge*2, "mm_med"); + memcpy(ndlm->medge, medge, sizeof(*medge)*totedge); + ndlm->totedge = totedge; + + for (i=0; i<totedge; i++) { + MEdge *med = &ndlm->medge[i]; + MEdge *nmed = &ndlm->medge[ndlm->totedge]; + + memcpy(nmed, med, sizeof(*med)); + + nmed->v1 = *((int*) ndlm->mvert[nmed->v1].no); + nmed->v2 = *((int*) ndlm->mvert[nmed->v2].no); + + if (nmed->v1!=med->v1 || nmed->v2!=med->v2) { + ndlm->totedge++; + } + } + } + + ndlm->mface = MEM_mallocN(sizeof(*mface)*totface*2, "mm_mf"); + memcpy(ndlm->mface, mface, sizeof(*mface)*totface); + + if (tface) { + ndlm->tface = MEM_mallocN(sizeof(*tface)*totface*2, "mm_tf"); + memcpy(ndlm->tface, tface, sizeof(*tface)*totface); + } else if (mcol) { + ndlm->mcol = MEM_mallocN(sizeof(*mcol)*4*totface*2, "mm_mcol"); + memcpy(ndlm->mcol, mcol, sizeof(*mcol)*4*totface); + } + + ndlm->totface = totface; + for (i=0; i<totface; i++) { + MFace *mf = &ndlm->mface[i]; + MFace *nmf = &ndlm->mface[ndlm->totface]; + TFace *tf, *ntf; + MCol *mc, *nmc; + + memcpy(nmf, mf, sizeof(*mf)); + if (tface) { + ntf = &ndlm->tface[ndlm->totface]; + tf = &ndlm->tface[i]; + memcpy(ntf, tf, sizeof(*tface)); + } else if (mcol) { + nmc = &ndlm->mcol[ndlm->totface*4]; + mc = &ndlm->mcol[i*4]; + memcpy(nmc, mc, sizeof(*mcol)*4); + } + + /* Map vertices to shared */ + + nmf->v1 = *((int*) ndlm->mvert[nmf->v1].no); + nmf->v2 = *((int*) ndlm->mvert[nmf->v2].no); + if (nmf->v3) { + nmf->v3 = *((int*) ndlm->mvert[nmf->v3].no); + if (nmf->v4) nmf->v4 = *((int*) ndlm->mvert[nmf->v4].no); + } + + /* If all vertices shared don't duplicate face */ + if (nmf->v1==mf->v1 && nmf->v2==mf->v2 && nmf->v3==mf->v3 && nmf->v4==mf->v4) + continue; + + if (nmf->v3) { + if (nmf->v4) { + int copyIdx; + + /* If three in order vertices are shared then duplicating the face + * will be strange (don't want two quads sharing three vertices in a + * mesh. Instead modify the original quad to leave out the middle vertice + * and span the gap. Vertice will remain in mesh and still have edges + * to it but will not interfere with normals. + */ + if (nmf->v4==mf->v4 && nmf->v1==mf->v1 && nmf->v2==mf->v2) { + mf->v1 = nmf->v3; + copyIdx = 0; + } else if (nmf->v1==mf->v1 && nmf->v2==mf->v2 && nmf->v3==mf->v3) { + mf->v2 = nmf->v4; + copyIdx = 1; + } else if (nmf->v2==mf->v2 && nmf->v3==mf->v3 && nmf->v4==mf->v4) { + mf->v3 = nmf->v1; + copyIdx = 2; + } else if (nmf->v3==mf->v3 && nmf->v4==mf->v4 && nmf->v1==mf->v1) { + mf->v4 = nmf->v2; + copyIdx = 3; + } else { + copyIdx = -1; + } + + if (copyIdx!=-1) { + int fromIdx = (copyIdx+2)%4; + + if (tface) { + tf->col[copyIdx] = ntf->col[fromIdx]; + tf->uv[copyIdx][0] = ntf->uv[fromIdx][0]; + tf->uv[copyIdx][1] = ntf->uv[fromIdx][1]; + } else if (mcol) { + mc[copyIdx] = nmc[fromIdx]; + } + + continue; + } + } + + /* Need to flip face normal, pick which verts to flip + * in order to prevent nmf->v3==0 or nmf->v4==0 + */ + if (nmf->v1) { + SWAP(int, nmf->v1, nmf->v3); + + if (tface) { + SWAP(unsigned int, ntf->col[0], ntf->col[2]); + SWAP(float, ntf->uv[0][0], ntf->uv[2][0]); + SWAP(float, ntf->uv[0][1], ntf->uv[2][1]); + } else if (mcol) { + SWAP(MCol, nmc[0], nmc[2]); + } + } else { + SWAP(int, nmf->v2, nmf->v4); + + if (tface) { + SWAP(unsigned int, ntf->col[1], ntf->col[3]); + SWAP(float, ntf->uv[1][0], ntf->uv[3][0]); + SWAP(float, ntf->uv[1][1], ntf->uv[3][1]); + } else if (mcol) { + SWAP(MCol, nmc[1], nmc[3]); + } + } + } + + ndlm->totface++; + } + + if (dlm) displistmesh_free(dlm); + if (dm) dm->release(dm); + + mesh_calc_normals(ndlm->mvert, ndlm->totvert, ndlm->mface, ndlm->totface, &ndlm->nors); + + return derivedmesh_from_displistmesh(ndlm); +} + /***/ static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES]; @@ -427,7 +636,6 @@ ModifierTypeInfo *modifierType_get_info(ModifierType type) mti->type = eModifierTypeType_Constructive; mti->flags = eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_SupportsMapping; mti->allocData = subsurfModifier_allocData; - mti->isDisabled = subsurfModifier_isDisabled; mti->applyModifier = subsurfModifier_applyModifier; mti = &typeArr[eModifierType_Build]; @@ -436,10 +644,17 @@ ModifierTypeInfo *modifierType_get_info(ModifierType type) mti->type = eModifierTypeType_Nonconstructive; mti->flags = eModifierTypeFlag_AcceptsMesh; mti->allocData = buildModifier_allocData; - mti->isDisabled = buildModifier_isDisabled; mti->dependsOnTime = buildModifier_dependsOnTime; mti->applyModifier = buildModifier_applyModifier; + mti = &typeArr[eModifierType_Mirror]; + strcpy(mti->name, "Mirror"); + strcpy(mti->structName, "MirrorModifierData"); + mti->type = eModifierTypeType_Constructive; + mti->flags = eModifierTypeFlag_AcceptsMesh; + mti->allocData = mirrorModifier_allocData; + mti->applyModifier = mirrorModifier_applyModifier; + typeArrInit = 0; } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index baa2a77bf10..5eb00c4f21b 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -11,6 +11,7 @@ typedef enum ModifierType { eModifierType_Lattice, eModifierType_Curve, eModifierType_Build, + eModifierType_Mirror, NUM_MODIFIER_TYPES } ModifierType; @@ -57,4 +58,11 @@ typedef struct BuildModifierData { int randomize, seed; } BuildModifierData; +typedef struct MirrorModifierData { + ModifierData modifier; + + int axis; + float tolerance; +} MirrorModifierData; + #endif diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 4f3e6ec9fcb..204f580096e 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -1832,6 +1832,12 @@ static void object_panel_modifiers(Object *ob) uiDefButF(block, NUM, B_MAKEDISP, "Length:", 550, 300, 150,19, &bmd->length, 1.0, 9000.0, 100, 0, "Specify the total time the build effect requires"); uiDefButI(block, TOG, B_MAKEDISP, "Randomize", 550, 280, 150,19, &bmd->randomize, 0, 0, 1, 0, "Randomize the faces or edges during build."); uiDefButI(block, NUM, B_MAKEDISP, "Seed:", 700, 280, 150,19, &bmd->seed, 1.0, 9000.0, 100, 0, "Specify the seed for random if used."); + } else if (md->type==eModifierType_Mirror) { + MirrorModifierData *mmd = (MirrorModifierData*) md; + uiDefButF(block, NUM, B_MAKEDISP, "Tolerance:", 550, 320, 150,19, &mmd->tolerance, 0.0, 1, 0, 0, "Distance from axis within which to share vertices"); + uiDefButI(block, ROW, B_MAKEDISP, "X", 550, 300, 20,19, &mmd->axis, 1, 0, 0, 0, "Specify the axis to mirror about"); + uiDefButI(block, ROW, B_MAKEDISP, "Y", 570, 300, 20,19, &mmd->axis, 1, 1, 0, 0, "Specify the axis to mirror about"); + uiDefButI(block, ROW, B_MAKEDISP, "Z", 590, 300, 20,19, &mmd->axis, 1, 2, 0, 0, "Specify the axis to mirror about"); } uiBlockEndAlign(block); |