From 1df154d14026daf7837f7ed6ea6553145436ae52 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Tue, 19 Jul 2005 20:14:17 +0000 Subject: [PATCH] - split {curve,lattice,armature}_deform_verts out of mesh_deform - removed mesh_deform (merge into mesh_modifier) - switch python lattice_apply function to use object_apply_deform, this isn't exactly equivalent but the python system shouldn't have been calling that deep into the kernel anyway. New feature: Modifier stack - added Object.modifiers (list of ModifierData elements) - added DNA_modifier_types.h o contains type definition for the file data for the various modifier types - added BKE_modifier.h o contains modifierType_get_info (access to modifier type registry) o structs and defines for runtime modifier usage - updated mesh_calc_modifiers to evaluate modifier stack (note that for the time being it also evaluates the old style modifiers so files should load and work as normal). - add file handling modifier code (todo: don't replicate on object copy) - add modifier stack UI code (lives in object panel) Only real new feature at the moment is that you can apply lattices and curves *after* a subdivision surface which was never possible before. Todo: - DEP graph updating does not work correctly yet, so you generally have to tab cycle to see results. - editmode calculation does not use modifier stack. - bug fixes (there must be a few in there somewhere) --- source/blender/blenkernel/BKE_lattice.h | 5 +- source/blender/blenkernel/BKE_modifier.h | 116 ++++++++++ source/blender/blenkernel/BKE_subsurf.h | 3 +- source/blender/blenkernel/SConscript | 1 + .../blender/blenkernel/intern/DerivedMesh.c | 139 +++++++++++- source/blender/blenkernel/intern/deform.c | 21 +- source/blender/blenkernel/intern/lattice.c | 89 ++++---- source/blender/blenkernel/intern/modifier.c | 181 ++++++++++++++++ source/blender/blenkernel/intern/object.c | 13 ++ .../blender/blenkernel/intern/subsurf_ccg.c | 50 +++-- source/blender/blenloader/intern/readfile.c | 21 ++ source/blender/blenloader/intern/writefile.c | 15 ++ source/blender/makesdna/DNA_modifier_types.h | 52 +++++ source/blender/makesdna/DNA_object_types.h | 1 + source/blender/makesdna/intern/makesdna.c | 2 + source/blender/python/api2_2x/Lattice.c | 26 +-- source/blender/src/buttons_object.c | 198 +++++++++++++++++- 17 files changed, 830 insertions(+), 103 deletions(-) create mode 100644 source/blender/blenkernel/BKE_modifier.h create mode 100644 source/blender/blenkernel/intern/modifier.c create mode 100644 source/blender/makesdna/DNA_modifier_types.h diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index fb3afc98df8..6b6bae6e4c4 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -50,11 +50,12 @@ void calc_lat_fudu(int flag, int res, float *fu, float *du); void init_latt_deform(struct Object *oblatt, struct Object *ob); void calc_latt_deform(float *co); void end_latt_deform(void); -int mesh_deform(struct Object *ob, float (*vertexCos)[3]); int object_deform(struct Object *ob); struct BPoint *latt_bp(struct Lattice *lt, int u, int v, int w); void outside_lattice(struct Lattice *lt); - +void curve_deform_verts(struct Object *cuOb, struct Object *target, float (*vertexCos)[3], int numVerts); +void lattice_deform_verts(struct Object *laOb, struct Object *target, float (*vertexCos)[3], int numVerts); +void armature_deform_verts(struct Object *armOb, struct Object *target, float (*vertexCos)[3], int numVerts); #endif diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h new file mode 100644 index 00000000000..651eb781fe7 --- /dev/null +++ b/source/blender/blenkernel/BKE_modifier.h @@ -0,0 +1,116 @@ +/** + * + * $$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_MODIFIER_H +#define BKE_MODIFIER_H + +struct DerivedMesh; +struct ModifierData; +struct Object; + +typedef enum { + /* Should not be used, only for None modifier type */ + eModifierTypeType_None, + + /* Modifier only does deformation, implies that modifier + * type should have a valid deformVerts function. OnlyDeform + * style modifiers implicitly accept either mesh or CV + * input but should still declare flags appropriately. + */ + eModifierTypeType_OnlyDeform, + + eModifierTypeType_Constructive, + eModifierTypeType_Nonconstructive, +} ModifierTypeType; + +typedef enum { + eModifierTypeFlag_AcceptsMesh = (1<<0), + eModifierTypeFlag_AcceptsCVs = (1<<1), + eModifierTypeFlag_SupportsMapping = (1<<2), + eModifierTypeFlag_RequiresObject = (1<<3), +} ModifierTypeFlag; + +typedef struct ModifierTypeInfo { + char name[32], structName[32]; + ModifierTypeType type; + ModifierTypeFlag flags; + + /* Create new instance data for this modifier type. + * + * This function must be present. + */ + struct ModifierData *(*allocData)(void); + + /* Return a boolean value indicating if this modifier is able to be calculated + * based on the modifier data. This is *not* regarding the md->flag, that is + * 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. + */ + int (*isDisabled)(struct ModifierData *md); + + /* Only for deform types, should apply the deformation + * to the given vertex array. Object is guaranteed to be + * non-NULL. + */ + void (*deformVerts)(struct ModifierData *md, struct Object *ob, float (*vertexCos)[3], int numVerts); + + /* For non-deform types: apply the modifier and return a new derived + * data object (type is dependent on object type). If the _derivedData_ + * argument is non-NULL then the modifier should read the object data + * from the derived object instead of the _data_ object. + * + * If the _vertexCos_ argument is non-NULL then the modifier should read + * the vertex coordinates from that (even if _derivedData_ is non-NULL). + * The length of the _vertexCos_ array is either the number of verts in + * the derived object (if non-NULL) or otherwise the number of verts in + * the original object. + * + * The _useRenderParams_ indicates if the modifier is being applied in + * the service of the renderer which may alter quality settings. + * + * The modifier is expected to release (or reuse) the _derivedData_ argument + * if non-NULL. The modifier *MAY NOT* share the _vertexCos_ argument. + * + * It is possible for _ob_ to be NULL if the modifier type is not flagged + * to require an object. A NULL _ob_ occurs when original coordinate data + * is requested for an object. + */ + void *(*applyModifier)(struct ModifierData *md, void *data, struct Object *ob, + void *derivedData, float (*vertexCos)[3], int useRenderParams); +} ModifierTypeInfo; + +ModifierTypeInfo *modifierType_get_info(ModifierType type); + +#endif + diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h index 3ae15d346bb..5443ab72760 100644 --- a/source/blender/blenkernel/BKE_subsurf.h +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -37,7 +37,8 @@ struct DerivedMesh; struct EditMesh; struct DerivedMesh *subsurf_make_derived_from_editmesh(struct EditMesh *em, int subdivLevels, short type, struct DerivedMesh *oldDerived); -struct DerivedMesh *subsurf_make_derived_from_mesh(struct Mesh *me, int subdivLevels, float (*vertCos)[3]); +struct DerivedMesh *subsurf_make_derived_from_mesh(struct Mesh *me, int subdivType, int subdivLevels, float (*vertCos)[3]); +struct DerivedMesh *subsurf_make_derived_from_dlm(struct DispListMesh *dlm, int subdivType, int subdivLevels); void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]); diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index a30c6488e05..66206f0cc98 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -19,6 +19,7 @@ source_files = ['intern/constraint.c', 'intern/deform.c', 'intern/image.c', 'intern/mesh.c', + 'intern/modifier.c', 'intern/screen.c', 'intern/anim.c', 'intern/displist.c', diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 3e6c4ee8587..4f89e8e5634 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -39,6 +39,7 @@ #include "DNA_effect_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" @@ -56,6 +57,7 @@ #include "BKE_object.h" #include "BKE_subsurf.h" #include "BKE_deform.h" +#include "BKE_modifier.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -1012,23 +1014,154 @@ DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm) /***/ -static void mesh_calc_modifiers(Mesh *me, Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParms, int useDeform) +static void mesh_calc_modifiers(Mesh *me, Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform) { + ModifierData *md=ob->modifiers.first; float (*deformedVerts)[3]; + DerivedMesh *dm; + int a, numVerts = me->totvert; if (deform_r) *deform_r = NULL; *final_r = NULL; + /* Note: useDeform==1 implies ob must be non-NULL */ + if (useDeform && ob) { mesh_modifier(ob, &deformedVerts); + if (!deformedVerts) { + deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "vertexcos1"); + for (a=0; amvert[a].co); + } + } + + /* Apply all leading deforming modifiers */ + for (; md; md=md->next) { + ModifierTypeInfo *mti = modifierType_get_info(md->type); + + if (!(md->mode&(1<isDisabled(md)) continue; + + if (mti->type==eModifierTypeType_OnlyDeform) { + mti->deformVerts(md, ob, deformedVerts, numVerts); + } else { + break; + } + } + + /* Result of all leading deforming modifiers is cached for + * places that wish to use the original mesh but with deformed + * coordinates (vpaint, etc.) + */ if (deform_r) *deform_r = getMeshDerivedMesh(me, ob, deformedVerts); } else { deformedVerts = inputVertexCos; } - if ((me->flag&ME_SUBSURF) && me->subdiv) { - *final_r = subsurf_make_derived_from_mesh(me, useRenderParms?me->subdivr:me->subdiv, deformedVerts); + /* Now apply all remaining modifiers. If useDeform is off then skip + * OnlyDeform ones. If we have no _ob_ and the modifier requires one + * also skip. + */ + dm = NULL; + for (; md; md=md->next) { + ModifierTypeInfo *mti = modifierType_get_info(md->type); + + if (!(md->mode&(1<type==eModifierTypeType_OnlyDeform && !useDeform) continue; + if (!ob && (mti->flags&eModifierTypeFlag_RequiresObject)) continue; + if (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 + * deformed vertices) and (b) what type the modifier is. + */ + + if (mti->type==eModifierTypeType_OnlyDeform) { + /* No existing verts to deform, need to build them. */ + if (!deformedVerts) { + if (dm) { + /* Deforming a derived mesh, read the vertex locations out of the mesh and + * deform them. Once done with this run of deformers will be written back. + */ + numVerts = dm->getNumVerts(dm); + deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv"); + dm->getVertCos(dm, deformedVerts); + } else { + numVerts = me->totvert; + deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "vertexcos2"); + for (a=0; amvert[a].co); + } + } + } + + mti->deformVerts(md, ob, deformedVerts, numVerts); + } else { + /* There are 4 cases here (have deform? have dm?) but they all are handled + * by the modifier apply function, which will also free the DerivedMesh if + * it exists. + */ + dm = mti->applyModifier(md, me, ob, dm, deformedVerts, useRenderParams); + + if (deformedVerts) { + if (deformedVerts!=inputVertexCos) { + MEM_freeN(deformedVerts); + } + deformedVerts = 0; + } + } + } + + /* Fake the subsurf modifier */ + { + int level = useRenderParams?me->subdivr:me->subdiv; + + if ((me->flag&ME_SUBSURF) && level) { + ModifierTypeInfo *mti = modifierType_get_info(eModifierType_Subsurf); + SubsurfModifierData smd; + + smd.levels = me->subdiv; + smd.renderLevels = me->subdivr; + smd.subdivType = me->subsurftype; + + dm = mti->applyModifier(&smd.modifier, me, ob, dm, deformedVerts, useRenderParams); + + if (deformedVerts) { + if (deformedVerts!=inputVertexCos) { + MEM_freeN(deformedVerts); + } + deformedVerts = 0; + } + } + } + + /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply + * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build + * one. + */ + if (dm && deformedVerts) { + DispListMesh *dlm = dm->convertToDispListMesh(dm); // XXX what if verts or nors were shared + int i; + + /* XXX, would like to avoid the conversion to a DLM here if possible. + * Requires adding a DerivedMesh.updateVertCos method. + */ + for (i=0; imvert[i].co, deformedVerts[i]); + } + + dm->release(dm); + + if (dlm->nors && !dlm->dontFreeNors) { + MEM_freeN(dlm->nors); + dlm->nors = 0; + } + + mesh_calc_normals(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface, &dlm->nors); + *final_r = derivedmesh_from_displistmesh(dlm); + } else if (dm) { + *final_r = dm; } else { *final_r = getMeshDerivedMesh(me, ob, deformedVerts); } diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 55b49744fbc..2b48e8bf101 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -248,7 +248,7 @@ void mesh_modifier(Object *ob, float (**vertexCos_r)[3]) if(me->totvert==0) return; - vertexCos = MEM_mallocN(sizeof(*vertexCos)*me->totvert, "vertexcos"); + vertexCos = MEM_mallocN(sizeof(*vertexCos)*me->totvert, "mm_vertexcos"); for (a=0; atotvert; a++) { VECCOPY(vertexCos[a], me->mvert[a].co); } @@ -288,8 +288,23 @@ void mesh_modifier(Object *ob, float (**vertexCos_r)[3]) sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos); } - /* object_deform: output for mesh is in mesh->mvert */ - done |= mesh_deform(ob, vertexCos); + if (ob->parent && me->totvert) { + if(ob->parent->type==OB_CURVE && ob->partype==PARSKEL) { + curve_deform_verts(ob->parent, ob, vertexCos, me->totvert); + done= 1; + } + else if(ob->parent->type==OB_LATTICE) { + lattice_deform_verts(ob->parent, ob, vertexCos, me->totvert); + done= 1; + } + else if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) { + // misleading making displists... very bad + if (ob->parent!=G.obedit) { + armature_deform_verts(ob->parent, ob, vertexCos, me->totvert); + } + done= 1; + } + } if((ob->softflag & OB_SB_ENABLE) && (ob->softflag & OB_SB_POSTDEF)) { done= 1; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index eff9d813afd..140c4d74822 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -516,64 +516,53 @@ static void calc_curve_deform(Object *par, float *co, short axis, CurveDeform *c } -int mesh_deform(Object *ob, float (*vertexCos)[3]) +void curve_deform_verts(Object *cuOb, Object *target, float (*vertexCos)[3], int numVerts) +{ + Curve *cu = cuOb->data; + int a, flag = cu->flag; + CurveDeform cd; + + cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist + + init_curve_deform(cuOb, target, &cd); + + INIT_MINMAX(cd.dmin, cd.dmax); + + for(a=0; atrackflag, &cd); + Mat4MulVecfl(cd.objectspace, vertexCos[a]); + } + + cu->flag = flag; +} + +void lattice_deform_verts(Object *laOb, Object *target, float (*vertexCos)[3], int numVerts) { - Mesh *me = ob->data; int a; - if(ob->parent==NULL || ob->type!=OB_MESH || !me->totvert) return 0; - - if(ob->parent->type==OB_CURVE && ob->partype==PARSKEL) { - Curve *cu = ob->parent->data; - int flag = cu->flag; - CurveDeform cd; - - cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist - - init_curve_deform(ob->parent, ob, &cd); - - /* transformation to curve space, and min max*/ - INIT_MINMAX(cd.dmin, cd.dmax); - - for(a=0; atotvert; a++) { - Mat4MulVecfl(cd.curvespace, vertexCos[a]); - DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax); - } + init_latt_deform(laOb, target); - for(a=0; atotvert; a++) { - calc_curve_deform(ob->parent, vertexCos[a], ob->trackflag, &cd); - Mat4MulVecfl(cd.objectspace, vertexCos[a]); /* move coord back to objectspace */ - } - - cu->flag = flag; - - return 1; + for(a=0; aparent->type==OB_LATTICE) { - init_latt_deform(ob->parent, ob); - if(ob->type==OB_MESH) { - for(a=0; atotvert; a++) { - calc_latt_deform(vertexCos[a]); - } - } - end_latt_deform(); - return 1; - } - else if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) { - if (ob->parent==G.obedit) // misleading making displists... very bad - return 1; - - init_armature_deform (ob->parent, ob); + end_latt_deform(); +} - for(a=0; atotvert; a++) { - calc_armature_deform(ob->parent, vertexCos[a], a); - } - - return 1; +void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts) +{ + int a; + + init_armature_deform(armOb, target); + + for(a=0; atype = type; + md->mode = eModifierMode_RealtimeAndRender; + + return md; +} + +static ModifierData *noneModifier_allocData(void) +{ + return allocModifierData(eModifierType_None, sizeof(ModifierData)); +} + +static int noneModifier_isDisabled(ModifierData *md) +{ + return 1; +} + +/* Curve */ + +static ModifierData *curveModifier_allocData(void) +{ + return allocModifierData(eModifierType_Curve, sizeof(CurveModifierData)); +} + +static int curveModifier_isDisabled(ModifierData *md) +{ + CurveModifierData *cmd = (CurveModifierData*) md; + + return !cmd->object; +} + +static void curveModifier_deformVerts(ModifierData *md, Object *ob, float (*vertexCos)[3], int numVerts) +{ + CurveModifierData *cmd = (CurveModifierData*) md; + + curve_deform_verts(cmd->object, ob, vertexCos, numVerts); +} + +/* Lattice */ + +static ModifierData *latticeModifier_allocData(void) +{ + return allocModifierData(eModifierType_Lattice, sizeof(LatticeModifierData)); +} + +static int latticeModifier_isDisabled(ModifierData *md) +{ + LatticeModifierData *lmd = (LatticeModifierData*) md; + + return !lmd->object; +} + +static void latticeModifier_deformVerts(ModifierData *md, Object *ob, float (*vertexCos)[3], int numVerts) +{ + LatticeModifierData *lmd = (LatticeModifierData*) md; + + lattice_deform_verts(lmd->object, ob, vertexCos, numVerts); +} + +/* Subsurf */ + +static ModifierData *subsurfModifier_allocData(void) +{ + SubsurfModifierData *smd = allocModifierData(eModifierType_Subsurf, sizeof(SubsurfModifierData)); + + smd->levels = 1; + smd->renderLevels = 2; + + return (ModifierData*) smd; +} + +static int subsurfModifier_isDisabled(ModifierData *md) +{ + return 0; +} + +static void *subsurfModifier_applyModifier(ModifierData *md, void *data, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int useRenderParams) +{ + SubsurfModifierData *smd = (SubsurfModifierData*) md; + int levels = useRenderParams?smd->renderLevels:smd->levels; + Mesh *me = data; + + if (dm) { + DispListMesh *dlm = dm->convertToDispListMesh(dm); // XXX what if verts were shared + int i; + + if (vertexCos) { + int numVerts = dm->getNumVerts(dm); + + for (i=0; imvert[i].co, vertexCos[i]); + } + } + dm->release(dm); + + dm = subsurf_make_derived_from_dlm(dlm, smd->subdivType, levels); + displistmesh_free(dlm); + + return dm; + } else { + return subsurf_make_derived_from_mesh(me, smd->subdivType, levels, vertexCos); + } +} + +/***/ + +static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES]; +static int typeArrInit = 1; + +ModifierTypeInfo *modifierType_get_info(ModifierType type) +{ + if (typeArrInit) { + ModifierTypeInfo *mti; + + memset(typeArr, 0, sizeof(typeArr)); + + mti = &typeArr[eModifierType_None]; + strcpy(mti->name, "None"); + strcpy(mti->structName, "ModifierData"); + mti->type = eModifierType_None; + mti->flags = eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_AcceptsCVs; + mti->allocData = noneModifier_allocData; + mti->isDisabled = noneModifier_isDisabled; + + mti = &typeArr[eModifierType_Curve]; + strcpy(mti->name, "Curve"); + strcpy(mti->structName, "CurveModifierData"); + mti->type = eModifierTypeType_OnlyDeform; + mti->flags = eModifierTypeFlag_AcceptsCVs; + mti->allocData = curveModifier_allocData; + mti->isDisabled = curveModifier_isDisabled; + mti->deformVerts = curveModifier_deformVerts; + + mti = &typeArr[eModifierType_Lattice]; + strcpy(mti->name, "Lattice"); + strcpy(mti->structName, "LatticeModifierData"); + mti->type = eModifierTypeType_OnlyDeform; + mti->flags = eModifierTypeFlag_AcceptsCVs; + mti->allocData = latticeModifier_allocData; + mti->isDisabled = latticeModifier_isDisabled; + mti->deformVerts = latticeModifier_deformVerts; + + mti = &typeArr[eModifierType_Subsurf]; + strcpy(mti->name, "Subsurf"); + strcpy(mti->structName, "SubsurfModifierData"); + mti->type = eModifierTypeType_Constructive; + mti->flags = eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_SupportsMapping; + mti->allocData = subsurfModifier_allocData; + mti->isDisabled = subsurfModifier_isDisabled; + mti->applyModifier = subsurfModifier_applyModifier; + + typeArrInit = 0; + } + + if (type>=0 && typefirst) { + BLI_remlink(lb, md); + MEM_freeN(md); + } +} + /* do not free object itself */ void free_object(Object *ob) { @@ -210,6 +221,7 @@ void free_object(Object *ob) free_effects(&ob->effect); BLI_freelistN(&ob->network); free_properties(&ob->prop); + free_modifiers(&ob->modifiers); free_sensors(&ob->sensors); free_controllers(&ob->controllers); @@ -807,6 +819,7 @@ Object *copy_object(Object *ob) obn->flag &= ~OB_FROMGROUP; copy_effects(&obn->effect, &ob->effect); + obn->modifiers.first = obn->modifiers.last= NULL; // XXX fixme obn->network.first= obn->network.last= 0; diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index b5222d21630..bf4d752daa8 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -73,6 +73,7 @@ typedef struct _SubSurf { Mesh *me; float (*vertCos)[3]; + DispListMesh *dlm; } SubSurf; typedef struct _VertData { @@ -144,13 +145,14 @@ static SubSurf *subSurf_fromEditmesh(EditMesh *em, int subdivLevels, int useAgin return ss; } -static SubSurf *subSurf_fromMesh(Mesh *me, int useFlatSubdiv, int subdivLevels, float (*vertCos)[3]) { +static SubSurf *subSurf_fromMesh(Mesh *me, int useFlatSubdiv, int subdivLevels, float (*vertCos)[3], DispListMesh *dlm) { SubSurf *ss = MEM_mallocN(sizeof(*ss), "ss_m"); ss->controlType = SUBSURF_CONTROLTYPE_MESH; ss->useAging=0; ss->subSurf = _getSubSurf(ss, subdivLevels, 1); ss->me = me; + ss->dlm = dlm; ss->vertCos = vertCos; ccgSubSurf_setAllowEdgeCreation(ss->subSurf, 1, useFlatSubdiv?subdivLevels:0.0f); @@ -505,28 +507,34 @@ static void subSurf_sync(SubSurf *ss, int useFlatSubdiv) { if (ss->controlType==SUBSURF_CONTROLTYPE_MESH) { CCGVertHDL fVerts[4]; + MVert *mvert = ss->dlm?ss->dlm->mvert:ss->me->mvert; + MEdge *medge = ss->dlm?ss->dlm->medge:ss->me->medge; + MFace *mface = ss->dlm?ss->dlm->mface:ss->me->mface; + int totvert = ss->dlm?ss->dlm->totvert:ss->me->totvert; + int totedge = ss->dlm?ss->dlm->totedge:ss->me->totedge; + int totface = ss->dlm?ss->dlm->totface:ss->me->totface; int i; if (ss->vertCos) { - for (i=0; ime->totvert; i++) { + for (i=0; isubSurf, (CCGVertHDL) i, ss->vertCos[i]); } } else { - for (i=0; ime->totvert; i++) { - ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, ss->me->mvert[i].co); + for (i=0; isubSurf, (CCGVertHDL) i, mvert[i].co); } } - if (ss->me->medge) { - for (i=0; ime->totedge; i++) { - MEdge *med = &ss->me->medge[i]; + if (medge) { + for (i=0; icrease*creaseFactor/255.0f; ccgSubSurf_syncEdge(ss->subSurf, (CCGEdgeHDL) i, (CCGVertHDL) med->v1, (CCGVertHDL) med->v2, crease); } } else { - for (i=0; ime->totface; i++) { - MFace *mf = &((MFace*) ss->me->mface)[i]; + for (i=0; iv3) { ccgSubSurf_syncEdge(ss->subSurf, (CCGEdgeHDL) i, (CCGVertHDL) mf->v1, (CCGVertHDL) mf->v2, useFlatSubdiv?creaseFactor:0.0); @@ -534,8 +542,8 @@ static void subSurf_sync(SubSurf *ss, int useFlatSubdiv) { } } - for (i=0; ime->totface; i++) { - MFace *mf = &((MFace*) ss->me->mface)[i]; + for (i=0; iv3) { fVerts[0] = (CCGVertHDL) mf->v1; @@ -1011,12 +1019,22 @@ DerivedMesh *subsurf_make_derived_from_editmesh(EditMesh *em, int subdivLevels, return (DerivedMesh*) ccgdm; } -DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, int subdivLevels, float (*vertCos)[3]) { - int useFlatSubdiv = me->subsurftype==ME_SIMPLE_SUBSURF; - SubSurf *ss = subSurf_fromMesh(me, useFlatSubdiv, subdivLevels, vertCos); +DerivedMesh *subsurf_make_derived_from_dlm(DispListMesh *dlm, int subdivType, int subdivLevels) { + SubSurf *ss = subSurf_fromMesh(NULL, subdivType==ME_SIMPLE_SUBSURF, subdivLevels, NULL, dlm); + + subSurf_sync(ss, subdivType==ME_SIMPLE_SUBSURF); + + dlm = subSurf_createDispListMesh(ss); + + subSurf_free(ss); + + return derivedmesh_from_displistmesh(dlm); +} +DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, int subdivType, int subdivLevels, float (*vertCos)[3]) { + SubSurf *ss = subSurf_fromMesh(me, subdivType==ME_SIMPLE_SUBSURF, subdivLevels, vertCos, NULL); DispListMesh *dlm; - subSurf_sync(ss, useFlatSubdiv); + subSurf_sync(ss, subdivType==ME_SIMPLE_SUBSURF); dlm = subSurf_createDispListMesh(ss); @@ -1032,7 +1050,7 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]) * calculated vert positions is incorrect for the verts * on the boundary of the mesh. */ - SubSurf *ss = subSurf_fromMesh(me, 0, 1, NULL); + SubSurf *ss = subSurf_fromMesh(me, 0, 1, NULL, NULL); float edge_sum[3], face_sum[3]; CCGVertIterator *vi; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 564017e0de6..436537ca39f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -79,6 +79,7 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" @@ -2110,8 +2111,23 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) /* ************ READ OBJECT ***************** */ +static void lib_link_modifier_data(FileData *fd, Object *ob, ModifierData *md) +{ + if (md->type==eModifierType_Lattice) { + LatticeModifierData *lmd = (LatticeModifierData*) md; + + lmd->object = newlibadr_us(fd, ob->id.lib, lmd->object); + } + else if (md->type==eModifierType_Curve) { + CurveModifierData *cmd = (CurveModifierData*) md; + + cmd->object = newlibadr_us(fd, ob->id.lib, cmd->object); + } +} + static void lib_link_object(FileData *fd, Main *main) { + ModifierData *md; Object *ob; bSensor *sens; bController *cont; @@ -2242,6 +2258,10 @@ static void lib_link_object(FileData *fd, Main *main) for(hook= ob->hooks.first; hook; hook= hook->next) { hook->parent= newlibadr(fd, ob->id.lib, hook->parent); } + + for (md=ob->modifiers.first; md; md= md->next) { + lib_link_modifier_data(fd, ob, md); + } } ob= ob->id.next; } @@ -2283,6 +2303,7 @@ static void direct_link_object(FileData *fd, Object *ob) ob->pose= newdataadr(fd, ob->pose); direct_link_pose(fd, ob->pose); + link_list(fd, &ob->modifiers); link_list(fd, &ob->defbase); link_list(fd, &ob->nlastrips); link_list(fd, &ob->constraintChannels); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 1e754dd3b90..3ee4e1be182 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -120,6 +120,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_material_types.h" +#include "DNA_modifier_types.h" #include "DNA_nla_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" @@ -155,6 +156,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi #include "BKE_scene.h" // for do_seq #include "BKE_sound.h" /* ... and for samples */ #include "BKE_utildefines.h" // for defines +#include "BKE_modifier.h" #include "GEN_messaging.h" @@ -657,6 +659,17 @@ static void write_constraint_channels(WriteData *wd, ListBase *chanbase) } +static void write_modifiers(WriteData *wd, ListBase *modbase) +{ + ModifierData *md; + + for (md=modbase->first; md; md= md->next) { + ModifierTypeInfo *mti = modifierType_get_info(md->type); + + writestruct(wd, DATA, mti->structName, 1, md); + } +} + static void write_objects(WriteData *wd, ListBase *idbase) { Object *ob; @@ -699,6 +712,8 @@ static void write_objects(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, "ObHook", 1, hook); writedata(wd, DATA, sizeof(int)*hook->totindex, hook->indexar); } + + write_modifiers(wd, &ob->modifiers); } ob= ob->id.next; } diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h new file mode 100644 index 00000000000..486fc68785c --- /dev/null +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -0,0 +1,52 @@ +/** + * $Id$ + */ + +#ifndef DNA_MODIFIER_TYPES_H +#define DNA_MODIFIER_TYPES_H + +typedef enum ModifierType { + eModifierType_None = 0, + eModifierType_Subsurf, + eModifierType_Lattice, + eModifierType_Curve, + + NUM_MODIFIER_TYPES +} ModifierType; + + /* These numerical values are explicitly chosen so that + * (mode&1) is true for realtime calc and (mode&2) is true + * for render calc. + */ +typedef enum ModifierMode { + eModifierMode_Disabled = 0, + eModifierMode_OnlyRealtime = 1, + eModifierMode_OnlyRender = 2, + eModifierMode_RealtimeAndRender = 3, +} ModifierMode; + +typedef struct ModifierData { + struct ModifierData *next, *prev; + + int type, mode; +} ModifierData; + +typedef struct SubsurfModifierData { + ModifierData modifier; + + short subdivType, levels, renderLevels, pad; +} SubsurfModifierData; + +typedef struct LatticeModifierData { + ModifierData modifier; + + struct Object *object; +} LatticeModifierData; + +typedef struct CurveModifierData { + ModifierData modifier; + + struct Object *object; +} CurveModifierData; + +#endif diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 5959f6da594..ee55dcb19fb 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -103,6 +103,7 @@ typedef struct Object { ListBase network; ListBase disp; ListBase defbase; + ListBase modifiers; /* list of ModifierData structures */ struct Material **mat; /* rot en drot have to be together! (transform('r' en 's')) */ diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 200639cd402..5a8a13f7d50 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -93,6 +93,7 @@ char *includefiles[] = { "DNA_curve_types.h", "DNA_mesh_types.h", "DNA_meshdata_types.h", + "DNA_modifier_types.h", "DNA_lattice_types.h", "DNA_object_types.h", "DNA_object_force.h", @@ -1107,6 +1108,7 @@ int main(int argc, char ** argv) #include "DNA_curve_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" #include "DNA_lattice_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" diff --git a/source/blender/python/api2_2x/Lattice.c b/source/blender/python/api2_2x/Lattice.c index efb19794e39..6fa7423f54f 100644 --- a/source/blender/python/api2_2x/Lattice.c +++ b/source/blender/python/api2_2x/Lattice.c @@ -705,26 +705,12 @@ static PyObject *Lattice_applyDeform( BPy_Lattice * self, PyObject *args ) * method is needed. Or for users who actually want to apply the * deformation n times. */ if((self->Lattice == par->data)) { - if ((base->object->type != OB_MESH) || forced) { - - if (base->object->type==OB_MESH) { - Mesh *me = base->object->data; - float (*vcos)[3] = malloc(sizeof(*vcos)*me->totvert); - int a; - - for (a=0; atotvert; a++) { - VECCOPY(vcos[a], me->mvert[a].co); - } - mesh_deform( base->object, vcos ); - for (a=0; atotvert; a++) { - VECCOPY(me->mvert[a].co, vcos[a]); - } - - free(vcos); - } else { - object_deform( base->object ); - } - } + /* I do not know what to do with this function + * at the moment given the changing modifier system. + * Calling into the modifier system in the first place + * isn't great... -zr + */ + object_apply_deform(base->object); } } base = base->next; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index b2845765e19..f57728318f1 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -95,6 +95,7 @@ #include "DNA_material_types.h" #include "DNA_meta_types.h" #include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_radio_types.h" @@ -120,6 +121,7 @@ #include "BKE_material.h" #include "BKE_mball.h" #include "BKE_mesh.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_sound.h" #include "BKE_texture.h" @@ -135,11 +137,6 @@ static float prspeed=0.0; float prlen=0.0; -/* ********************* function prototypes ******************** */ -void object_panel_draw(Object *); -void object_panel_hooks(Object *); -void object_panel_effects(Object *); - /* ********************* CONSTRAINT ***************************** */ #if 0 @@ -974,7 +971,7 @@ static void object_panel_constraint(void) } } -void object_panel_draw(Object *ob) +static void object_panel_draw(Object *ob) { uiBlock *block; int xco, a, dx, dy; @@ -1031,7 +1028,7 @@ void object_panel_draw(Object *ob) } -void object_panel_hooks(Object *ob) +static void object_panel_hooks(Object *ob) { uiBlock *block; ObHook *hook; @@ -1654,7 +1651,191 @@ static void object_softbodies(Object *ob) } -void object_panel_effects(Object *ob) +/* Modifiers */ + +static int actModifier = 0; + +static void modifiers_add(void *ob_v, int type) +{ + Object *ob = ob_v; + ModifierTypeInfo *mti = modifierType_get_info(type); + + if (mti) { + ModifierData *md = mti->allocData(); + + BLI_addtail(&ob->modifiers, md); + + md->type = type; + actModifier = BLI_countlist(&ob->modifiers); + + allqueue(REDRAWBUTSOBJECT, 0); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + } +} + +static uiBlock *modifier_add_menu(void *ob_v) +{ + Object *ob = ob_v; + uiBlock *block; + int i, yco=0; + + block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu", UI_EMBOSSP, UI_HELV, curarea->win); + uiBlockSetButmFunc(block, modifiers_add, ob); + + for (i=eModifierType_None+1; iflags&eModifierTypeFlag_AcceptsCVs) || + (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) { + uiDefBut(block, BUTM, B_NOP, mti->name, 0, yco-=20, 160, 19, NULL, 0, 0, 1, i, ""); + } + } + + uiTextBoundsBlock(block, 50); + uiBlockSetDirection(block, UI_DOWN); + + return block; +} + +static void modifiers_del(void *ob_v, void *arg2) +{ + Object *ob = ob_v; + ModifierData *md; + int i; + + for (i=0, md=ob->modifiers.first; md && inext; + + if (md) { + BLI_remlink(&ob->modifiers, md); + MEM_freeN(md); + } + + allqueue(REDRAWBUTSOBJECT, 0); +} + +static void modifiers_moveUp(void *ob_v, void *md_v) +{ + Object *ob = ob_v; + ModifierData *md = md_v; + + if (md->prev) { + BLI_remlink(&ob->modifiers, md); + BLI_insertlink(&ob->modifiers, md->prev->prev, md); + actModifier--; + } + + allqueue(REDRAWBUTSOBJECT, 0); +} + +static void modifiers_moveDown(void *ob_v, void *md_v) +{ + Object *ob = ob_v; + ModifierData *md = md_v; + + if (md->next) { + BLI_remlink(&ob->modifiers, md); + BLI_insertlink(&ob->modifiers, md->next, md); + actModifier++; + } + + allqueue(REDRAWBUTSOBJECT, 0); +} + +static void modifier_testLatticeObj(char *name, ID **idpp) +{ + ID *id; + + for (id= G.main->object.first; id; id= id->next) { + if( strcmp(name, id->name+2)==0 ) { + if (((Object *)id)->type != OB_LATTICE) { + error ("Lattice deform object must be a lattice"); + break; + } + *idpp= id; + return; + } + } + *idpp= 0; +} + +static void modifier_testCurveObj(char *name, ID **idpp) +{ + ID *id; + + for (id= G.main->object.first; id; id= id->next) { + if( strcmp(name, id->name+2)==0 ) { + if (((Object *)id)->type != OB_CURVE) { + error ("Curve deform object must be a curve"); + break; + } + *idpp= id; + return; + } + } + *idpp= 0; +} + +static void object_panel_modifiers(Object *ob) +{ + uiBlock *block; + uiBut *but; + + block= uiNewBlock(&curarea->uiblocks, "modifiers_panel", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Constraints", "Object"); + if(uiNewPanel(curarea, block, "Modifiers", "Object", 640, 0, 318, 204)==0) return; + + uiBlockBeginAlign(block); + uiDefBlockBut(block, modifier_add_menu, ob, "Add Modifier", 550,400,124,27, "Append a new modifier"); + but = uiDefBut(block, BUT, B_MAKEDISP, "Delete", 676,400,62,27, 0, 0, 0, 0, 0, "Delete the current modifier"); + uiButSetFunc(but, modifiers_del, ob, NULL); + uiBlockEndAlign(block); + + if (ob->modifiers.first) { + int i, numModifiers = BLI_countlist(&ob->modifiers); + ModifierData *md; + + CLAMP(actModifier, 1, numModifiers); + uiDefButI(block, NUM, B_REDR, "Modifier", 760,400,160,27, &actModifier, 1, numModifiers, 0, 0, "Index of current modifier"); + + for (i=0, md=ob->modifiers.first; md && inext; + + if (md) { + static char *modifier_mode_menu ="Modifier Mode%t|Disabled%x0|Only Realtime%x1|Only Render%x2|Realtime & Render%x3"; + ModifierTypeInfo *mti = modifierType_get_info(md->type); + char str[128]; + + but = uiDefBut(block, BUT, B_MAKEDISP, "Move Up", 760, 380, 80, 19, 0, 0, 0, 0, 0, "Move modifier up in stack"); + uiButSetFunc(but, modifiers_moveUp, ob, md); + but = uiDefBut(block, BUT, B_MAKEDISP, "Move Down", 840, 380, 80, 19, 0, 0, 0, 0, 0, "Move modifier up in stack"); + uiButSetFunc(but, modifiers_moveDown, ob, md); + + sprintf(str, "Modifier: %s", mti->name); + uiDefBut(block, LABEL, 1, str, 550, 360, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); + but = uiDefButI(block, MENU, B_MAKEDISP, modifier_mode_menu, 550, 340, 160,19, &md->mode, 0, 0, 0, 0, "Modifier calculation mode"); + uiBlockBeginAlign(block); + if (md->type==eModifierType_Subsurf) { + SubsurfModifierData *smd = (SubsurfModifierData*) md; + char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1"; + uiDefButS(block, NUM, B_MAKEDISP, "Levels:", 550, 320, 150,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform"); + uiDefButS(block, NUM, B_MAKEDISP, "Render Levels:", 550, 300, 150,19, &smd->renderLevels, 1, 6, 0, 0, "Number subdivisions to perform when rendering"); + uiDefButS(block, MENU, B_MAKEDISP, subsurfmenu, 550,280,150,19, &(smd->subdivType), 0, 0, 0, 0, "Selects type of subdivision algorithm."); + } else if (md->type==eModifierType_Lattice) { + LatticeModifierData *lmd = (LatticeModifierData*) md; + uiDefIDPoinBut(block, modifier_testLatticeObj, B_MAKEDISP, "Ob:", 550, 320, 120,19, &lmd->object, "Lattice object to deform with"); + } else if (md->type==eModifierType_Curve) { + CurveModifierData *cmd = (CurveModifierData*) md; + uiDefIDPoinBut(block, modifier_testCurveObj, B_MAKEDISP, "Ob:", 550, 320, 120,19, &cmd->object, "Lattice object to deform with"); + } + uiBlockEndAlign(block); + } + } +} + +/***/ + +static void object_panel_effects(Object *ob) { Effect *eff; uiBlock *block; @@ -1814,6 +1995,7 @@ void object_panels() object_panel_constraint(); if(ob->type==OB_MESH) { object_panel_effects(ob); + object_panel_modifiers(ob); } object_panel_deflectors(ob); object_softbodies(ob);