Wow! A new feature!
- made ModifierData.isDisabled optional - Added new modifier type: Mirror o modifier system isn't running in editmode yet so still don't have mirrored editing, but otherwise it is pretty cool. code even goes to tricks to make sure mirror join looks nice in degenerate cases. o this kind of commit is basically the upshot of all the previous commits - in that implementing a new modifier changes only about 3 files and still integrates nearly completely.
This commit is contained in:
parent
eb9d466b48
commit
dc232fda47
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue