- split {curve,lattice,armature}_deform_verts out of mesh_deform
authorDaniel Dunbar <daniel@zuster.org>
Tue, 19 Jul 2005 20:14:17 +0000 (20:14 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Tue, 19 Jul 2005 20:14:17 +0000 (20:14 +0000)
 - 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)

17 files changed:
source/blender/blenkernel/BKE_lattice.h
source/blender/blenkernel/BKE_modifier.h [new file with mode: 0644]
source/blender/blenkernel/BKE_subsurf.h
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/deform.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/modifier.c [new file with mode: 0644]
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/makesdna/DNA_modifier_types.h [new file with mode: 0644]
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/intern/makesdna.c
source/blender/python/api2_2x/Lattice.c
source/blender/src/buttons_object.c

index fb3afc98df807be51c5bbdab768c100e77074b12..6b6bae6e4c4f248c37423b09cf57f3a21e20c230 100644 (file)
@@ -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 (file)
index 0000000..651eb78
--- /dev/null
@@ -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
+
index 3ae15d346bb669d39627622480fa46f674198bb8..5443ab727600bc9f765a4bcf8059e7c823f43f36 100644 (file)
@@ -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]);
 
index a30c6488e05d86bb719d68d4d570572f85c1c5d2..66206f0cc98675739f575daf7fa48c157f0b8b96 100644 (file)
@@ -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',
index 3e6c4ee8587d7785703e7cbbf625c6e9700771a0..4f89e8e5634f79d83b9e503aa67fac40716e93d3 100644 (file)
@@ -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; a<numVerts; a++) {
+                               VECCOPY(deformedVerts[a], me->mvert[a].co);
+                       }
+               }
+
+                       /* Apply all leading deforming modifiers */
+               for (; md; md=md->next) {
+                       ModifierTypeInfo *mti = modifierType_get_info(md->type);
+
+                       if (!(md->mode&(1<<useRenderParams))) continue;
+                       if (mti->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<<useRenderParams))) continue;
+               if (mti->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; a<numVerts; a++) {
+                                               VECCOPY(deformedVerts[a], me->mvert[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; i<numVerts; i++) {
+                       VECCOPY(dlm->mvert[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);
        }
index 55b49744fbcb1a8624a608176e7ad4dbf2fc5082..2b48e8bf1013a25140880a7581577ccbde322785 100644 (file)
@@ -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; a<me->totvert; 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;
index eff9d813afda6babf08b2d99f12aa1462a80d7c8..140c4d7482226d2d363b175a8e49d07f6ca7f501 100644 (file)
@@ -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)
 {
-       Mesh *me = ob->data;
-       int a;
-
-       if(ob->parent==NULL || ob->type!=OB_MESH || !me->totvert) return 0;
+       Curve *cu = cuOb->data;
+       int a, flag = cu->flag;
+       CurveDeform cd;
        
-       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(cuOb, target, &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; a<me->totvert; a++) {
-                       Mat4MulVecfl(cd.curvespace, vertexCos[a]);
-                       DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
-               }
+       INIT_MINMAX(cd.dmin, cd.dmax);
+               
+       for(a=0; a<numVerts; a++) {
+               Mat4MulVecfl(cd.curvespace, vertexCos[a]);
+               DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
+       }
 
-               for(a=0; a<me->totvert; a++) {
-                       calc_curve_deform(ob->parent, vertexCos[a], ob->trackflag, &cd);
-                       Mat4MulVecfl(cd.objectspace, vertexCos[a]); /* move coord back to objectspace */
-               }
+       for(a=0; a<numVerts; a++) {
+               calc_curve_deform(cuOb, vertexCos[a], target->trackflag, &cd);
+               Mat4MulVecfl(cd.objectspace, vertexCos[a]);
+       }
 
-               cu->flag = flag;
+       cu->flag = flag;
+}
 
-               return 1;
-       }
-       else if(ob->parent->type==OB_LATTICE) {
-               init_latt_deform(ob->parent, ob);
-               if(ob->type==OB_MESH) {
-                       for(a=0; a<me->totvert; a++) {
-                               calc_latt_deform(vertexCos[a]);
-                       }
-               }
-               end_latt_deform();
+void lattice_deform_verts(Object *laOb, Object *target, float (*vertexCos)[3], int numVerts)
+{
+       int a;
 
-               return 1;
+       init_latt_deform(laOb, target);
+
+       for(a=0; a<numVerts; a++) {
+               calc_latt_deform(vertexCos[a]);
        }
-       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);
 
-               for(a=0; a<me->totvert; a++) {
-                       calc_armature_deform(ob->parent, vertexCos[a], a);
-               }
-               
-               return 1;
+       end_latt_deform();
+}
+
+void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts) 
+{
+       int a;
+
+       init_armature_deform(armOb, target);
+
+       for(a=0; a<numVerts; a++) {
+               calc_armature_deform(armOb, vertexCos[a], a);
        }
-       
-       return 0;
 }
 
 int object_deform(Object *ob)
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
new file mode 100644 (file)
index 0000000..dd0f909
--- /dev/null
@@ -0,0 +1,181 @@
+#include "string.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_displist.h"
+#include "BKE_modifier.h"
+#include "BKE_lattice.h"
+#include "BKE_subsurf.h"
+
+/***/
+
+static void *allocModifierData(int type, int size)
+{
+       ModifierData *md = MEM_callocN(size, "md");
+       md->type = 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; i<numVerts; i++) {
+                               VECCOPY(dlm->mvert[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 && type<NUM_MODIFIER_TYPES && typeArr[type].name[0]!='\0') {
+               return &typeArr[type];
+       } else {
+               return NULL;
+       }
+}
+
index 1661711fc60b9df5bee7f898c7ce867c0c362efa..00134a9c03a3da450c48cd0bcff56a0ad7ab6d7e 100644 (file)
@@ -54,6 +54,7 @@
 #include "DNA_material_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"
 #include "DNA_oops_types.h"
@@ -170,6 +171,16 @@ static void copy_hooks(ListBase *new, ListBase *old)
 
 }
 
+static void free_modifiers(ListBase *lb)
+{
+       ModifierData *md;
+
+       while (md=lb->first) {
+               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;
        
index b5222d216306a7a0e226980e0fe97ea100545862..bf4d752daa856f22355eab27291a2af83503b871 100644 (file)
@@ -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; i<ss->me->totvert; i++) {
+                       for (i=0; i<totvert; i++) {
                                ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, ss->vertCos[i]);
                        }
                } else {
-                       for (i=0; i<ss->me->totvert; i++) {
-                               ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, ss->me->mvert[i].co);
+                       for (i=0; i<totvert; i++) {
+                               ccgSubSurf_syncVert(ss->subSurf, (CCGVertHDL) i, mvert[i].co);
                        }
                }
 
-               if (ss->me->medge) {
-                       for (i=0; i<ss->me->totedge; i++) {
-                               MEdge *med = &ss->me->medge[i];
+               if (medge) {
+                       for (i=0; i<totedge; i++) {
+                               MEdge *med = &medge[i];
                                float crease = useFlatSubdiv?creaseFactor:med->crease*creaseFactor/255.0f;
 
                                ccgSubSurf_syncEdge(ss->subSurf, (CCGEdgeHDL) i, (CCGVertHDL) med->v1, (CCGVertHDL) med->v2, crease);
                        }
                } else {
-                       for (i=0; i<ss->me->totface; i++) {
-                               MFace *mf = &((MFace*) ss->me->mface)[i];
+                       for (i=0; i<totface; i++) {
+                               MFace *mf = &((MFace*) mface)[i];
 
                                if (!mf->v3) {
                                        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; i<ss->me->totface; i++) {
-                       MFace *mf = &((MFace*) ss->me->mface)[i];
+               for (i=0; i<totface; i++) {
+                       MFace *mf = &((MFace*) mface)[i];
 
                        if (mf->v3) {
                                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;
 
index 564017e0de68234fc2ea6e1f7d2d292193fe8053..436537ca39f50d71f2456ceb224741c8822e8521 100644 (file)
@@ -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);
index 1e754dd3b9094babf08a8ac6b9f407c97d426fb8..3ee4e1be1827b88ef61f9afc6ff5d72384ed966d 100644 (file)
@@ -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 (file)
index 0000000..486fc68
--- /dev/null
@@ -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
index 5959f6da594cdd3a52d2e8a37f7ba354ea1f824b..ee55dcb19fbd3011df98e812167ebc4f8bb5d415 100644 (file)
@@ -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')) */
index 200639cd402c409f9ae7324763ef4c31014ac905..5a8a13f7d508dcf5281a1e75bb23f1956316f795 100644 (file)
@@ -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"
index efb19794e39d775c6df7edac1f436808d9ebe5ac..6fa7423f54f4f5cc053eed8bce903a19131771e7 100644 (file)
@@ -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; a<me->totvert; a++) {
-                                                       VECCOPY(vcos[a], me->mvert[a].co);
-                                               }
-                                               mesh_deform( base->object, vcos );
-                                               for (a=0; a<me->totvert; 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;
index b2845765e19d9b1051c88b2d3df1267faac8ab07..f57728318f1c1b2b7a9eff18f1120f5b18627f2f 100644 (file)
@@ -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"
 #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; i<NUM_MODIFIER_TYPES; i++) {
+               ModifierTypeInfo *mti = modifierType_get_info(i);
+
+               if (    (mti->flags&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 && i<actModifier-1; i++)
+               md = md->next;
+
+       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 && i<actModifier-1; i++)
+                       md = md->next;
+
+               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);