--- /dev/null
- #include "BKE_customdata.h"
+/**
+ * BKE_cloth.h
+ *
+ * $Id: BKE_cloth.h,v 1.1 2007/08/01 02:07:27 daniel Exp $
+ *
+ * ***** 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) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_CLOTH_H
+#define BKE_CLOTH_H
+
++#include "BKE_customdata.h"
+#include "BLI_linklist.h"
+#include "BKE_DerivedMesh.h"
++#include "BKE_object.h"
++
++#include "DNA_cloth_types.h"
+#include "DNA_customdata_types.h"
- void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr);
- void cloth_free_modifier ( ClothModifierData *clmd );
+#include "DNA_meshdata_types.h"
+
+struct Object;
+struct Cloth;
+struct MFace;
+struct DerivedMesh;
++struct ClothModifierData;
+
+// this is needed for inlining behaviour
+
+#ifndef _WIN32
+#define LINUX
+#define DO_INLINE inline
+#else
+#define DO_INLINE
+#endif
+
+#define CLOTH_MAX_THREAD 2
+
+
+typedef struct ClothVertex {
+ int flags; /* General flags per vertex. */
+ float mass; /* mass / weight of the vertex */
+ float goal; /* goal, from SB */
+ float impulse[3]; /* used in collision.c */
+ unsigned int impulse_count; /* same as above */
+ float collball;
+} ClothVertex;
+
+typedef struct ClothSpring {
+ int ij; /* Pij from the paper, one end of the spring. */
+ int kl; /* Pkl from the paper, one end of the spring. */
+ float restlen; /* The original length of the spring. */
+ int matrix_index; /* needed for implicit solver (fast lookup) */
+ int type; /* types defined in BKE_cloth.h ("springType") */
+ int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */
+ float dfdx[3][3];
+ float dfdv[3][3];
+ float f[3];
+} ClothSpring;
+
+typedef struct Cloth {
+ struct ClothVertex *verts; /* The vertices that represent this cloth. */
+ struct LinkNode *springs; /* The springs connecting the mesh. */
+ struct BVH *tree; /* collision tree for this cloth object */
+ struct BVH *selftree; /* self collision tree for this cloth object */
+ struct MFace *mfaces;
+ struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
+ struct EdgeHash *edgehash; /* used for fast checking adjacent points */
+ unsigned int numverts; /* The number of verts == m * n. */
+ unsigned int numsprings; /* The count of springs. */
+ unsigned int numfaces;
+ unsigned int numothersprings;
+ unsigned int numspringssave;
+ unsigned int old_solver_type;
+ float (*x)[3]; /* The current position of all vertices.*/
+ float (*xold)[3]; /* The previous position of all vertices.*/
+ float (*current_x)[3]; /* The TEMPORARY current position of all vertices.*/
+ float (*current_xold)[3]; /* The TEMPORARY previous position of all vertices.*/
+ float (*v)[4]; /* the current velocity of all vertices */
+ float (*current_v)[3];
+ float (*xconst)[3];
+} Cloth;
+
+/* goal defines */
+#define SOFTGOALSNAP 0.999f
+
+/* This is approximately the smallest number that can be
+* represented by a float, given its precision. */
+#define ALMOST_ZERO 0.000001
+
+// some macro enhancements for vector treatment
+#define VECADDADD(v1,v2,v3) {*(v1)+= *(v2) + *(v3); *(v1+1)+= *(v2+1) + *(v3+1); *(v1+2)+= *(v2+2) + *(v3+2);}
+#define VECSUBADD(v1,v2,v3) {*(v1)-= *(v2) + *(v3); *(v1+1)-= *(v2+1) + *(v3+1); *(v1+2)-= *(v2+2) + *(v3+2);}
+#define VECADDSUB(v1,v2,v3) {*(v1)+= *(v2) - *(v3); *(v1+1)+= *(v2+1) - *(v3+1); *(v1+2)+= *(v2+2) - *(v3+2);}
+#define VECSUBADDSS(v1,v2,aS,v3,bS) {*(v1)-= *(v2)*aS + *(v3)*bS; *(v1+1)-= *(v2+1)*aS + *(v3+1)*bS; *(v1+2)-= *(v2+2)*aS + *(v3+2)*bS;}
+#define VECADDSUBSS(v1,v2,aS,v3,bS) {*(v1)+= *(v2)*aS - *(v3)*bS; *(v1+1)+= *(v2+1)*aS - *(v3+1)*bS; *(v1+2)+= *(v2+2)*aS - *(v3+2)*bS;}
+#define VECADDSS(v1,v2,aS,v3,bS) {*(v1)= *(v2)*aS + *(v3)*bS; *(v1+1)= *(v2+1)*aS + *(v3+1)*bS; *(v1+2)= *(v2+2)*aS + *(v3+2)*bS;}
+#define VECADDS(v1,v2,v3,bS) {*(v1)= *(v2) + *(v3)*bS; *(v1+1)= *(v2+1) + *(v3+1)*bS; *(v1+2)= *(v2+2) + *(v3+2)*bS;}
+#define VECSUBMUL(v1,v2,aS) {*(v1)-= *(v2) * aS; *(v1+1)-= *(v2+1) * aS; *(v1+2)-= *(v2+2) * aS;}
+#define VECSUBS(v1,v2,v3,bS) {*(v1)= *(v2) - *(v3)*bS; *(v1+1)= *(v2+1) - *(v3+1)*bS; *(v1+2)= *(v2+2) - *(v3+2)*bS;}
+#define VECSUBSB(v1,v2, v3,bS) {*(v1)= (*(v2)- *(v3))*bS; *(v1+1)= (*(v2+1) - *(v3+1))*bS; *(v1+2)= (*(v2+2) - *(v3+2))*bS;}
+#define VECMULS(v1,aS) {*(v1)*= aS; *(v1+1)*= aS; *(v1+2)*= *aS;}
+#define VECADDMUL(v1,v2,aS) {*(v1)+= *(v2) * aS; *(v1+1)+= *(v2+1) * aS; *(v1+2)+= *(v2+2) * aS;}
+
+/* SIMULATION FLAGS: goal flags,.. */
+/* These are the bits used in SimSettings.flags. */
+typedef enum
+{
+ CLOTH_SIMSETTINGS_FLAG_RESET = ( 1 << 1 ), // The CM object requires a reinitializaiton.
+ CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ), // object is only collision object, no cloth simulation is done
+ CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), // we have goals enabled
+ CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ), // true if tearing is enabled
+ CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ),
+ CLOTH_SIMSETTINGS_FLAG_BIG_FORCE = ( 1 << 6 ), // true if we have big spring force for bending
+ CLOTH_SIMSETTINGS_FLAG_SLEEP = ( 1 << 7 ), // true if we let the cloth go to sleep
+} CLOTH_SIMSETTINGS_FLAGS;
+
+/* SPRING FLAGS */
+typedef enum
+{
+ CLOTH_COLLISIONSETTINGS_FLAG_ENABLED = ( 1 << 1 ),
+} CLOTH_COLLISIONSETTINGS_FLAGS;
+
+/* Spring types as defined in the paper.*/
+typedef enum
+{
+ CLOTH_SPRING_TYPE_STRUCTURAL = 0,
+ CLOTH_SPRING_TYPE_SHEAR,
+ CLOTH_SPRING_TYPE_BENDING,
+} CLOTH_SPRING_TYPES;
+
+/* SPRING FLAGS */
+typedef enum
+{
+ CLOTH_SPRING_FLAG_DEACTIVATE = ( 1 << 1 ),
+ CLOTH_SPRING_FLAG_NEEDED = ( 1 << 2 ), // springs has values to be applied
+} CLOTH_SPRINGS_FLAGS;
+
+/* Bits to or into the ClothVertex.flags. */
+#define CVERT_FLAG_PINNED 1
+#define CVERT_FLAG_COLLISION 2
+
+
+// needed for buttons_object.c
- void implicit_set_positions ( ClothModifierData *clmd );
++void cloth_clear_cache(struct Object *ob, struct ClothModifierData *clmd, float framenr);
++void cloth_free_modifier ( struct ClothModifierData *clmd );
+
+// needed for cloth.c
- DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc);
++void implicit_set_positions ( struct ClothModifierData *clmd );
+
+// from cloth.c, needed for modifier.c
- int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, float dt);
++DerivedMesh *clothModifier_do(struct ClothModifierData *clmd, struct Object *ob, struct DerivedMesh *dm, int useRenderParams, int isFinalCalc);
+
+// needed in implicit.c
- void cloth_free_modifier ( ClothModifierData *clmd );
- void cloth_init ( ClothModifierData *clmd );
++int cloth_bvh_objcollision(struct ClothModifierData *clmd, float step, float prevstep, float dt);
+
+////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////
+// cloth.c
+////////////////////////////////////////////////
- typedef void ( *CM_COLLISION_SELF ) ( ClothModifierData *clmd, int step );
++void cloth_free_modifier ( struct ClothModifierData *clmd );
++void cloth_init ( struct ClothModifierData *clmd );
+////////////////////////////////////////////////
+
+
+/* Typedefs for function pointers we need for solvers and collision detection. */
- int ( *init ) ( Object *ob, ClothModifierData *clmd );
- int ( *solver ) ( Object *ob, float framenr, ClothModifierData *clmd, ListBase *effectors );
- int ( *free ) ( ClothModifierData *clmd );
++typedef void ( *CM_COLLISION_SELF ) ( struct ClothModifierData *clmd, int step );
+// typedef void ( *CM_COLLISION_OBJ ) ( ClothModifierData *clmd, int step, CM_COLLISION_RESPONSE collision_response );
+
+
+/* This enum provides the IDs for our solvers. */
+// only one available in the moment
+typedef enum {
+ CM_IMPLICIT = 0,
+ CM_VERLET = 1,
+} CM_SOLVER_ID;
+
+
+/* This structure defines how to call the solver.
+*/
+typedef struct
+{
+ char *name;
+ CM_SOLVER_ID id;
- int implicit_init ( Object *ob, ClothModifierData *clmd );
- int implicit_free ( ClothModifierData *clmd );
- int implicit_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors );
++ int ( *init ) ( struct Object *ob, struct ClothModifierData *clmd );
++ int ( *solver ) ( struct Object *ob, float framenr, struct ClothModifierData *clmd, struct ListBase *effectors );
++ int ( *free ) ( struct ClothModifierData *clmd );
+}
+CM_SOLVER_DEF;
+
+
+/* new C implicit simulator */
- int verlet_init ( Object *ob, ClothModifierData *clmd );
- int verlet_free ( ClothModifierData *clmd );
- int verlet_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors );
++int implicit_init ( struct Object *ob, struct ClothModifierData *clmd );
++int implicit_free ( struct ClothModifierData *clmd );
++int implicit_solver ( struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors );
+
+/* explicit verlet simulator */
++int verlet_init ( struct Object *ob, struct ClothModifierData *clmd );
++int verlet_free ( struct ClothModifierData *clmd );
++int verlet_solver ( struct Object *ob, float frame, struct ClothModifierData *clmd, struct ListBase *effectors );
+
+
+/* used for collisions in collision.c */
+/*
+typedef struct CollPair
+{
+ unsigned int face1; // cloth face
+ unsigned int face2; // object face
+ double distance; // magnitude of vector
+ float normal[3];
+ float vector[3]; // unnormalized collision vector: p2-p1
+ float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
+ int lastsign; // indicates if the distance sign has changed, unused itm
+ float time; // collision time, from 0 up to 1
+ unsigned int ap1, ap2, ap3, bp1, bp2, bp3, bp4;
+ unsigned int pointsb[4];
+}
+CollPair;
+*/
+
+/* used for collisions in collision.c */
+typedef struct EdgeCollPair
+{
+ unsigned int p11, p12, p21, p22;
+ float normal[3];
+ float vector[3];
+ float time;
+ int lastsign;
+ float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
+}
+EdgeCollPair;
+
+/* used for collisions in collision.c */
+typedef struct FaceCollPair
+{
+ unsigned int p11, p12, p13, p21;
+ float normal[3];
+ float vector[3];
+ float time;
+ int lastsign;
+ float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
+}
+FaceCollPair;
+
+// function definitions from implicit.c
+DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar);
+
+#endif
+
int *lastPossibleCageIndex_r);
int modifiers_isSoftbodyEnabled(struct Object *ob);
+struct ClothModifierData *modifiers_isClothEnabled(Object *ob);
+ int modifiers_isParticleEnabled(struct Object *ob);
++
struct Object *modifiers_isDeformedByArmature(struct Object *ob);
struct Object *modifiers_isDeformedByLattice(struct Object *ob);
int modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
#include "DNA_ID.h"
- #define PTCache_EXT ".bphys"
- #define PTCache_PATH "//pointcache/"
+ /* options for clearing pointcache - used for BKE_ptcache_id_clear
+ Before and after are non inclusive (they wont remove the cfra) */
+ #define PTCACHE_CLEAR_ALL 0
+ #define PTCACHE_CLEAR_FRAME 1
+ #define PTCACHE_CLEAR_BEFORE 2
+ #define PTCACHE_CLEAR_AFTER 3
- int PTCache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext);
- FILE * PTCache_id_fopen(struct ID *id, char mode, int cfra, int stack_index);
- void PTCache_id_clear(struct ID *id, int cfra, int stack_index);
+ #define PTCACHE_EXT ".bphys"
+ #define PTCACHE_PATH "//pointcache/"
+
-int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext);
++int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext);
+ FILE * BKE_ptcache_id_fopen(struct ID *id, char mode, int cfra, int stack_index);
+ void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index);
#endif
--- /dev/null
- PTCache_id_clear((ID *)ob, framenr, stack_index);
+/* cloth.c
+*
+*
+* ***** 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) Blender Foundation
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): none yet.
+*
+* ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+/* types */
+#include "DNA_curve_types.h"
+#include "DNA_cloth_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_key_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_edgehash.h"
+#include "BLI_linklist.h"
+
+#include "BKE_curve.h"
+#include "BKE_cloth.h"
+#include "BKE_collisions.h"
+#include "BKE_deform.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_mesh.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+#include "BKE_pointcache.h"
+#include "BKE_utildefines.h"
+
+#include "BIF_editdeform.h"
+#include "BIF_editkey.h"
+#include "DNA_screen_types.h"
+#include "BSE_headerbuttons.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "mydevice.h"
+
+#ifdef _WIN32
+void tstart ( void )
+{}
+void tend ( void )
+{
+}
+double tval()
+{
+ return 0;
+}
+#else
+#include <sys/time.h>
+ static struct timeval _tstart, _tend;
+ static struct timezone tz;
+ void tstart ( void )
+{
+ gettimeofday ( &_tstart, &tz );
+}
+void tend ( void )
+{
+ gettimeofday ( &_tend,&tz );
+}
+double tval()
+{
+ double t1, t2;
+ t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 );
+ t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 );
+ return t2-t1;
+}
+#endif
+
+/* Our available solvers. */
+// 255 is the magic reserved number, so NEVER try to put 255 solvers in here!
+// 254 = MAX!
+static CM_SOLVER_DEF solvers [] =
+{
+ { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free },
+ // { "Verlet", CM_VERLET, verlet_init, verlet_solver, verlet_free },
+};
+
+/* ********** cloth engine ******* */
+/* Prototypes for internal functions.
+*/
+static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd);
+static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr);
+static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr);
+
+int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm );
+static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup);
+/******************************************************************************
+*
+* External interface called by modifier.c clothModifier functions.
+*
+******************************************************************************/
+/**
+ * cloth_init - creates a new cloth simulation.
+ *
+ * 1. create object
+ * 2. fill object with standard values or with the GUI settings if given
+ */
+void cloth_init (ClothModifierData *clmd)
+{
+ /* Initialize our new data structure to reasonable values. */
+ clmd->sim_parms->gravity [0] = 0.0;
+ clmd->sim_parms->gravity [1] = 0.0;
+ clmd->sim_parms->gravity [2] = -9.81;
+ clmd->sim_parms->structural = 100.0;
+ clmd->sim_parms->shear = 100.0;
+ clmd->sim_parms->bending = 1.0;
+ clmd->sim_parms->Cdis = 5.0;
+ clmd->sim_parms->Cvi = 1.0;
+ clmd->sim_parms->mass = 1.0f;
+ clmd->sim_parms->stepsPerFrame = 5;
+ clmd->sim_parms->sim_time = 1.0;
+ clmd->sim_parms->flags = CLOTH_SIMSETTINGS_FLAG_RESET;
+ clmd->sim_parms->solver_type = 0;
+ clmd->sim_parms->preroll = 0;
+ clmd->sim_parms->maxspringlen = 10;
+ clmd->coll_parms->self_friction = 5.0;
+ clmd->coll_parms->friction = 10.0;
+ clmd->coll_parms->loop_count = 1;
+ clmd->coll_parms->epsilon = 0.01;
+ clmd->coll_parms->selfepsilon = 0.1;
+
+ /* These defaults are copied from softbody.c's
+ * softbody_calc_forces() function.
+ */
+ clmd->sim_parms->eff_force_scale = 1000.0;
+ clmd->sim_parms->eff_wind_scale = 250.0;
+
+ // also from softbodies
+ clmd->sim_parms->maxgoal = 1.0;
+ clmd->sim_parms->mingoal = 0.0;
+ clmd->sim_parms->defgoal = 0.0;
+ clmd->sim_parms->goalspring = 100.0;
+ clmd->sim_parms->goalfrict = 0.0;
+}
+
+// unused in the moment, cloth needs quads from mesh
+DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm)
+{
+ /*
+ DerivedMesh *result = NULL;
+ int i;
+ int numverts = dm->getNumVerts(dm);
+ int numedges = dm->getNumEdges(dm);
+ int numfaces = dm->getNumFaces(dm);
+
+ MVert *mvert = CDDM_get_verts(dm);
+ MEdge *medge = CDDM_get_edges(dm);
+ MFace *mface = CDDM_get_faces(dm);
+
+ MVert *mvert2;
+ MFace *mface2;
+ unsigned int numtris=0;
+ unsigned int numquads=0;
+ int a = 0;
+ int random = 0;
+ int firsttime = 0;
+ float vec1[3], vec2[3], vec3[3], vec4[3], vec5[3];
+ float mag1=0, mag2=0;
+
+ for(i = 0; i < numfaces; i++)
+ {
+ if(mface[i].v4)
+ numquads++;
+ else
+ numtris++;
+}
+
+ result = CDDM_from_template(dm, numverts, 0, numtris + 2*numquads);
+
+ if(!result)
+ return NULL;
+
+ // do verts
+ mvert2 = CDDM_get_verts(result);
+ for(a=0; a<numverts; a++)
+ {
+ MVert *inMV;
+ MVert *mv = &mvert2[a];
+
+ inMV = &mvert[a];
+
+ DM_copy_vert_data(dm, result, a, a, 1);
+ *mv = *inMV;
+}
+
+
+ // do faces
+ mface2 = CDDM_get_faces(result);
+ for(a=0, i=0; a<numfaces; a++)
+ {
+ MFace *mf = &mface2[i];
+ MFace *inMF;
+ inMF = &mface[a];
+
+
+ // DM_copy_face_data(dm, result, a, i, 1);
+
+ // *mf = *inMF;
+
+
+ if(mface[a].v4 && random==1)
+ {
+ mf->v1 = mface[a].v2;
+ mf->v2 = mface[a].v3;
+ mf->v3 = mface[a].v4;
+}
+ else
+ {
+ mf->v1 = mface[a].v1;
+ mf->v2 = mface[a].v2;
+ mf->v3 = mface[a].v3;
+}
+
+ mf->v4 = 0;
+ mf->flag |= ME_SMOOTH;
+
+ test_index_face(mf, NULL, 0, 3);
+
+ if(mface[a].v4)
+ {
+ MFace *mf2;
+
+ i++;
+
+ mf2 = &mface2[i];
+
+ // DM_copy_face_data(dm, result, a, i, 1);
+
+ // *mf2 = *inMF;
+
+
+ if(random==1)
+ {
+ mf2->v1 = mface[a].v1;
+ mf2->v2 = mface[a].v2;
+ mf2->v3 = mface[a].v4;
+}
+ else
+ {
+ mf2->v1 = mface[a].v4;
+ mf2->v2 = mface[a].v1;
+ mf2->v3 = mface[a].v3;
+}
+ mf2->v4 = 0;
+ mf2->flag |= ME_SMOOTH;
+
+ test_index_face(mf2, NULL, 0, 3);
+}
+
+ i++;
+}
+
+ CDDM_calc_edges(result);
+ CDDM_calc_normals(result);
+
+ return result;
+ */
+
+ return NULL;
+}
+
+
+DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm)
+{
+ /*
+ DerivedMesh *result = NULL;
+ unsigned int i = 0, a = 0, j=0;
+ int numverts = dm->getNumVerts(dm);
+ int numedges = dm->getNumEdges(dm);
+ int numfaces = dm->getNumFaces(dm);
+
+ MVert *mvert = CDDM_get_verts(dm);
+ MEdge *medge = CDDM_get_edges(dm);
+ MFace *mface = CDDM_get_faces(dm);
+
+ MVert *mvert2;
+ MFace *mface2;
+ unsigned int numtris=0;
+ unsigned int numquads=0;
+ EdgeHash *edgehash = NULL;
+ Cloth *cloth = clmd->clothObject;
+ ClothSpring *springs = cloth->springs;
+ unsigned int numsprings = cloth->numsprings;
+
+ // create spring tearing hash
+ edgehash = BLI_edgehash_new();
+
+ for(i = 0; i < numsprings; i++)
+ {
+ if((springs[i].flags & CSPRING_FLAG_DEACTIVATE)
+ &&(!BLI_edgehash_haskey(edgehash, springs[i].ij, springs[i].kl)))
+ {
+ BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL);
+ BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL);
+ j++;
+}
+}
+
+ // printf("found %d tears\n", j);
+
+ result = CDDM_from_template(dm, numverts, 0, numfaces);
+
+ if(!result)
+ return NULL;
+
+ // do verts
+ mvert2 = CDDM_get_verts(result);
+ for(a=0; a<numverts; a++)
+ {
+ MVert *inMV;
+ MVert *mv = &mvert2[a];
+
+ inMV = &mvert[a];
+
+ DM_copy_vert_data(dm, result, a, a, 1);
+ *mv = *inMV;
+}
+
+
+ // do faces
+ mface2 = CDDM_get_faces(result);
+ for(a=0, i=0; a<numfaces; a++)
+ {
+ MFace *mf = &mface2[i];
+ MFace *inMF;
+ inMF = &mface[a];
+
+
+ // DM_copy_face_data(dm, result, a, i, 1);
+
+ // *mf = *inMF;
+
+
+ if((!BLI_edgehash_haskey(edgehash, mface[a].v1, mface[a].v2))
+ &&(!BLI_edgehash_haskey(edgehash, mface[a].v2, mface[a].v3))
+ &&(!BLI_edgehash_haskey(edgehash, mface[a].v3, mface[a].v4))
+ &&(!BLI_edgehash_haskey(edgehash, mface[a].v4, mface[a].v1)))
+ {
+ mf->v1 = mface[a].v1;
+ mf->v2 = mface[a].v2;
+ mf->v3 = mface[a].v3;
+ mf->v4 = mface[a].v4;
+
+ test_index_face(mf, NULL, 0, 4);
+
+ i++;
+}
+}
+
+ CDDM_lower_num_faces(result, i);
+ CDDM_calc_edges(result);
+ CDDM_calc_normals(result);
+
+ BLI_edgehash_free(edgehash, NULL);
+
+ return result;
+ */
+
+ return NULL;
+}
+
+int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
+
+void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
+{
+ int stack_index = -1;
+
+ if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT))
+ {
+ stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd);
+
- fp = PTCache_id_fopen((ID *)ob, 'w', framenr, stack_index);
++ BKE_ptcache_id_clear((ID *)ob, PTCACHE_CLEAR_AFTER, framenr, stack_index);
+ }
+}
+static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr)
+{
+ FILE *fp = NULL;
+ int stack_index = -1;
+ unsigned int a;
+ Cloth *cloth = clmd->clothObject;
+
+ if(!cloth)
+ return;
+
+ stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd);
+
- fp = PTCache_id_fopen((ID *)ob, 'r', framenr, stack_index);
++ fp = BKE_ptcache_id_fopen((ID *)ob, 'w', framenr, stack_index);
+ if(!fp) return;
+
+ for(a = 0; a < cloth->numverts; a++)
+ {
+ fwrite(&cloth->x[a], sizeof(float),4,fp);
+ fwrite(&cloth->xconst[a], sizeof(float),4,fp);
+ fwrite(&cloth->v[a], sizeof(float),4,fp);
+ }
+
+ fclose(fp);
+}
+static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr)
+{
+ FILE *fp = NULL;
+ int stack_index = -1;
+ unsigned int a, ret = 1;
+ Cloth *cloth = clmd->clothObject;
+
+ if(!cloth)
+ return 0;
+
+ stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd);
+
- unsigned int i = 0;
++ fp = BKE_ptcache_id_fopen((ID *)ob, 'r', framenr, stack_index);
+ if(!fp)
+ ret = 0;
+ else {
+ for(a = 0; a < cloth->numverts; a++)
+ {
+ if(fread(&cloth->x[a], sizeof(float), 4, fp) != 4)
+ {
+ ret = 0;
+ break;
+ }
+ if(fread(&cloth->xconst[a], sizeof(float), 4, fp) != 4)
+ {
+ ret = 0;
+ break;
+ }
+ if(fread(&cloth->v[a], sizeof(float), 4, fp) != 4)
+ {
+ ret = 0;
+ break;
+ }
+ }
+
+ fclose(fp);
+ }
+
+ implicit_set_positions(clmd);
+
+ return ret;
+}
+
+/************************************************
+ * clothModifier_do - main simulation function
+************************************************/
+DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
+{
+ unsigned int i;
+ unsigned int numverts = -1;
+ unsigned int numedges = -1;
+ unsigned int numfaces = -1;
+ MVert *mvert = NULL;
+ MEdge *medge = NULL;
+ MFace *mface = NULL;
+ DerivedMesh *result = NULL;
+ Cloth *cloth = clmd->clothObject;
+ unsigned int framenr = (float)G.scene->r.cfra;
+ float current_time = bsystem_time(ob, (float)G.scene->r.cfra, 0.0);
+ ListBase *effectors = NULL;
+ float deltaTime = current_time - clmd->sim_parms->sim_time;
+
+ clmd->sim_parms->dt = 1.0f / (clmd->sim_parms->stepsPerFrame * G.scene->r.frs_sec);
+
+ result = CDDM_copy(dm);
+
+ if(!result)
+ {
+ return dm;
+ }
+
+ numverts = result->getNumVerts(result);
+ numedges = result->getNumEdges(result);
+ numfaces = result->getNumFaces(result);
+ mvert = CDDM_get_verts(result);
+ medge = CDDM_get_edges(result);
+ mface = CDDM_get_faces(result);
+
+ clmd->sim_parms->sim_time = current_time;
+
+ if ( current_time < clmd->sim_parms->firstframe )
+ return result;
+
+ // only be active during a specific period:
+ // that's "first frame" and "last frame" on GUI
+ /*
+ if ( clmd->clothObject )
+ {
+ if ( clmd->sim_parms->cache )
+ {
+ if ( current_time < clmd->sim_parms->firstframe )
+ {
+ int frametime = cloth_cache_first_frame ( clmd );
+ if ( cloth_cache_search_frame ( clmd, frametime ) )
+ {
+ cloth_cache_get_frame ( clmd, frametime );
+ cloth_to_object ( ob, result, clmd );
+}
+ return result;
+}
+ else if ( current_time > clmd->sim_parms->lastframe )
+ {
+ int frametime = cloth_cache_last_frame ( clmd );
+ if ( cloth_cache_search_frame ( clmd, frametime ) )
+ {
+ cloth_cache_get_frame ( clmd, frametime );
+ cloth_to_object ( ob, result, clmd );
+}
+ return result;
+}
+ else if ( ABS ( deltaTime ) >= 2.0f ) // no timewarps allowed
+ {
+ if ( cloth_cache_search_frame ( clmd, framenr ) )
+ {
+ cloth_cache_get_frame ( clmd, framenr );
+ cloth_to_object ( ob, result, clmd );
+}
+ clmd->sim_parms->sim_time = current_time;
+ return result;
+}
+}
+}
+ */
+
+ if(deltaTime == 1.0f)
+ {
+ if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) )
+ {
+ cloth_clear_cache(ob, clmd, 0);
+
+ if(!cloth_from_object (ob, clmd, result, dm, framenr))
+ return result;
+
+ if(clmd->clothObject == NULL)
+ return result;
+
+ cloth = clmd->clothObject;
+ }
+
+ clmd->clothObject->old_solver_type = clmd->sim_parms->solver_type;
+
+ // Insure we have a clmd->clothObject, in case allocation failed.
+ if (clmd->clothObject != NULL)
+ {
+ if(!cloth_read_cache(ob, clmd, framenr))
+ {
+ // Force any pinned verts to their constrained location.
+ // has to be commented for verlet
+ for ( i = 0; i < clmd->clothObject->numverts; i++ )
+ {
+ // Save the previous position.
+ VECCOPY ( cloth->xold[i], cloth->xconst[i] );
+ VECCOPY ( cloth->current_xold[i], cloth->x[i] );
+ // Get the current position.
+ VECCOPY ( cloth->xconst[i], mvert[i].co );
+ Mat4MulVecfl ( ob->obmat, cloth->xconst[i] );
+ }
+
+ tstart();
+
+ /* Call the solver. */
+ if (solvers [clmd->sim_parms->solver_type].solver)
+ solvers [clmd->sim_parms->solver_type].solver (ob, framenr, clmd, effectors);
+
+ tend();
+
+ printf("Cloth simulation time: %f\n", tval());
+
+ cloth_write_cache(ob, clmd, framenr);
+ }
+
+ // Copy the result back to the object.
+ cloth_to_object (ob, result, clmd);
+
+ // bvh_free(clmd->clothObject->tree);
+ // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms->epsilon);
+ }
+
+ }
+ else if ( ( deltaTime <= 0.0f ) || ( deltaTime > 1.0f ) )
+ {
+ if ( clmd->clothObject != NULL )
+ {
+ if(cloth_read_cache(ob, clmd, framenr))
+ cloth_to_object (ob, result, clmd);
+ }
+ }
+
+ return result;
+}
+
+/* frees all */
+void cloth_free_modifier (ClothModifierData *clmd)
+{
+ Cloth *cloth = NULL;
+
+ if(!clmd)
+ return;
+
+ cloth = clmd->clothObject;
+
+ // free our frame cache
+ // cloth_clear_cache(ob, clmd, 0);
+
+ /* Calls the solver and collision frees first as they
+ * might depend on data in clmd->clothObject. */
+
+ if (cloth)
+ {
+ // If our solver provides a free function, call it
+ if (cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free)
+ {
+ solvers [cloth->old_solver_type].free (clmd);
+ }
+
+ // Free the verts.
+ if (cloth->verts != NULL)
+ MEM_freeN (cloth->verts);
+
+ // Free the faces.
+ if ( cloth->mfaces != NULL )
+ MEM_freeN ( cloth->mfaces );
+
+ // Free the verts.
+ if ( cloth->x != NULL )
+ MEM_freeN ( cloth->x );
+
+ // Free the verts.
+ if ( cloth->xold != NULL )
+ MEM_freeN ( cloth->xold );
+
+ // Free the verts.
+ if ( cloth->v != NULL )
+ MEM_freeN ( cloth->v );
+
+ // Free the verts.
+ if ( cloth->current_x != NULL )
+ MEM_freeN ( cloth->current_x );
+
+ // Free the verts.
+ if ( cloth->current_xold != NULL )
+ MEM_freeN ( cloth->current_xold );
+
+ // Free the verts.
+ if ( cloth->current_v != NULL )
+ MEM_freeN ( cloth->current_v );
+
+ // Free the verts.
+ if ( cloth->xconst != NULL )
+ MEM_freeN ( cloth->xconst );
+
+ cloth->verts = NULL;
+ cloth->numverts = -1;
+
+ // Free the springs.
+ if ( cloth->springs != NULL )
+ {
+ LinkNode *search = cloth->springs;
+ while(search)
+ {
+ ClothSpring *spring = search->link;
+
+ MEM_freeN ( spring );
+ search = search->next;
+ }
+ BLI_linklist_free(cloth->springs, NULL);
+
+ cloth->springs = NULL;
+ }
+
+ cloth->numsprings = -1;
+
+ // free BVH collision tree
+ if(cloth->tree)
+ bvh_free((BVH *)cloth->tree);
+
+ // free BVH self collision tree
+ if(cloth->selftree)
+ bvh_free((BVH *)cloth->selftree);
+
+ if(cloth->edgehash)
+ BLI_edgehash_free ( cloth->edgehash, NULL );
+
+ MEM_freeN (cloth);
+ clmd->clothObject = NULL;
+ }
+
+}
+
+
+
+/******************************************************************************
+*
+* Internal functions.
+*
+******************************************************************************/
+
+/**
+ * cloth_to_object - copies the deformed vertices to the object.
+ *
+ * This function is a modified version of the softbody.c:softbody_to_object() function.
+ **/
+static void cloth_to_object (Object *ob, DerivedMesh *dm, ClothModifierData *clmd)
+{
+ unsigned int i = 0;
+ MVert *mvert = NULL;
+ unsigned int numverts;
+ Cloth *cloth = clmd->clothObject;
+
+ if (clmd->clothObject) {
+ /* inverse matrix is not uptodate... */
+ Mat4Invert (ob->imat, ob->obmat);
+
+ mvert = CDDM_get_verts(dm);
+ numverts = dm->getNumVerts(dm);
+
+ for (i = 0; i < numverts; i++)
+ {
+ VECCOPY (mvert[i].co, cloth->x[i]);
+ Mat4MulVecfl (ob->imat, mvert[i].co); /* cloth is in global coords */
+ }
+ }
+}
+
+
+/**
+ * cloth_apply_vgroup - applies a vertex group as specified by type
+ *
+ **/
+static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short vgroup)
+{
+ unsigned int i = 0;
+ unsigned int j = 0;
+ MDeformVert *dvert = NULL;
+ Cloth *clothObj = NULL;
+ unsigned int numverts = 0;
+ float goalfac = 0;
+ ClothVertex *verts = NULL;
+
+ clothObj = clmd->clothObject;
+
+ if ( !dm )
+ return;
+
+ numverts = dm->getNumVerts(dm);
+
+ /* vgroup is 1 based, decrement so we can match the right group. */
+ --vgroup;
+
+ verts = clothObj->verts;
+
+ for ( i = 0; i < numverts; i++, verts++ )
+ {
+ // LATER ON, support also mass painting here
+ if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
+ {
+ dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT );
+ if ( dvert )
+ {
+ for ( j = 0; j < dvert->totweight; j++ )
+ {
+ if ( dvert->dw[j].def_nr == vgroup )
+ {
+ verts->goal = dvert->dw [j].weight;
+
+ goalfac= ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal );
+ verts->goal = ( float ) pow ( verts->goal , 4.0f );
+
+ if ( dvert->dw [j].weight >=SOFTGOALSNAP )
+ {
+ verts->flags |= CVERT_FLAG_PINNED;
+ }
+
+ // TODO enable mass painting here, for the moment i let "goals" go first
+
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+// only meshes supported at the moment
+static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr)
+{
+ unsigned int i;
+ unsigned int numverts = dm->getNumVerts(dm);
+ MVert *mvert = CDDM_get_verts(dm);
+ float tnull[3] = {0,0,0};
+
+ /* If we have a clothObject, free it. */
+ if (clmd->clothObject != NULL)
+ cloth_free_modifier (clmd);
+
+ /* Allocate a new cloth object. */
+ clmd->clothObject = MEM_callocN (sizeof(Cloth), "cloth");
+ if (clmd->clothObject)
+ {
+ clmd->clothObject->old_solver_type = 255;
+ clmd->clothObject->edgehash = NULL;
+ }
+ else if (clmd->clothObject == NULL)
+ {
+ modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject.");
+ return 0;
+ }
+
+ switch (ob->type)
+ {
+ case OB_MESH:
+
+ // mesh input objects need DerivedMesh
+ if ( !dm )
+ return 0;
+
+ cloth_from_mesh (ob, clmd, dm, framenr);
+
+ if ( clmd->clothObject != NULL )
+ {
+ /* create springs */
+ clmd->clothObject->springs = NULL;
+ clmd->clothObject->numsprings = -1;
+
+ /* set initial values */
+ for (i = 0; i < numverts; ++i)
+ {
+ VECCOPY (clmd->clothObject->x[i], mvert[i].co);
+ Mat4MulVecfl(ob->obmat, clmd->clothObject->x[i]);
+
+ clmd->clothObject->verts [i].mass = clmd->sim_parms->mass;
+ if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
+ clmd->clothObject->verts [i].goal= clmd->sim_parms->defgoal;
+ else
+ clmd->clothObject->verts [i].goal= 0.0;
+ clmd->clothObject->verts [i].flags = 0;
+ VECCOPY(clmd->clothObject->xold[i], clmd->clothObject->x[i]);
+ VECCOPY(clmd->clothObject->xconst[i], clmd->clothObject->x[i]);
+ VECCOPY(clmd->clothObject->current_xold[i], clmd->clothObject->x[i]);
+ VecMulf(clmd->clothObject->v[i], 0.0);
+
+ clmd->clothObject->verts [i].impulse_count = 0;
+ VECCOPY ( clmd->clothObject->verts [i].impulse, tnull );
+ }
+
+ if (!cloth_build_springs (clmd->clothObject, dm) )
+ {
+ modifier_setError (&(clmd->modifier), "Can't build springs.");
+ return 0;
+ }
+
+ /* apply / set vertex groups */
+ if (clmd->sim_parms->vgroup_mass > 0)
+ cloth_apply_vgroup (clmd, olddm, clmd->sim_parms->vgroup_mass);
+
+ /* init our solver */
+ if (solvers [clmd->sim_parms->solver_type].init)
+ solvers [clmd->sim_parms->solver_type].init (ob, clmd);
+
+ clmd->clothObject->tree = bvh_build_from_float3(CDDM_get_faces(dm), dm->getNumFaces(dm), clmd->clothObject->x, numverts, clmd->coll_parms->epsilon);
+
+ clmd->clothObject->selftree = bvh_build_from_float3(NULL, 0, clmd->clothObject->x, numverts, clmd->coll_parms->selfepsilon);
+
+ // save initial state
+ cloth_write_cache(ob, clmd, framenr-1);
+ }
+ return 1;
+ default: return 0; // TODO - we do not support changing meshes
+ }
+
+ return 0;
+}
+
+static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr)
+{
+ unsigned int numverts = dm->getNumVerts(dm);
+ unsigned int numfaces = dm->getNumFaces(dm);
+ MFace *mface = CDDM_get_faces(dm);
+
+ /* Allocate our vertices.
+ */
+ clmd->clothObject->numverts = numverts;
+ clmd->clothObject->verts = MEM_callocN (sizeof (ClothVertex) * clmd->clothObject->numverts, "clothVertex");
+ if (clmd->clothObject->verts == NULL)
+ {
+ cloth_free_modifier (clmd);
+ modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts.");
+ return;
+ }
+
+ clmd->clothObject->x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_x" );
+ if ( clmd->clothObject->x == NULL )
+ {
+ cloth_free_modifier ( clmd );
+ modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->x." );
+ return;
+ }
+
+ clmd->clothObject->xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_xold" );
+ if ( clmd->clothObject->xold == NULL )
+ {
+ cloth_free_modifier ( clmd );
+ modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xold." );
+ return;
+ }
+
+ clmd->clothObject->v = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_v" );
+ if ( clmd->clothObject->v == NULL )
+ {
+ cloth_free_modifier ( clmd );
+ modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->v." );
+ return;
+ }
+
+ clmd->clothObject->current_x = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_current_x" );
+ if ( clmd->clothObject->current_x == NULL )
+ {
+ cloth_free_modifier ( clmd );
+ modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_x." );
+ return;
+ }
+
+ clmd->clothObject->current_xold = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_current_xold" );
+ if ( clmd->clothObject->current_xold == NULL )
+ {
+ cloth_free_modifier ( clmd );
+ modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_xold." );
+ return;
+ }
+
+ clmd->clothObject->current_v = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_current_v" );
+ if ( clmd->clothObject->current_v == NULL )
+ {
+ cloth_free_modifier ( clmd );
+ modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->current_v." );
+ return;
+ }
+
+ clmd->clothObject->xconst = MEM_callocN ( sizeof ( float ) * clmd->clothObject->numverts * 4, "Cloth MVert_xconst" );
+ if ( clmd->clothObject->xconst == NULL )
+ {
+ cloth_free_modifier ( clmd );
+ modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xconst." );
+ return;
+ }
+
+ // save face information
+ clmd->clothObject->numfaces = numfaces;
+ clmd->clothObject->mfaces = MEM_callocN (sizeof (MFace) * clmd->clothObject->numfaces, "clothMFaces");
+ if (clmd->clothObject->mfaces == NULL)
+ {
+ cloth_free_modifier (clmd);
+ modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject->mfaces.");
+ return;
+ }
+ memcpy(clmd->clothObject->mfaces, mface, sizeof(MFace)*numfaces);
+
+ /* Free the springs since they can't be correct if the vertices
+ * changed.
+ */
+ if (clmd->clothObject->springs != NULL)
+ MEM_freeN (clmd->clothObject->springs);
+
+}
+
+/***************************************************************************************
+* SPRING NETWORK BUILDING IMPLEMENTATION BEGIN
+***************************************************************************************/
+
+// be carefull: implicit solver has to be resettet when using this one!
+int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type)
+{
+ Cloth *cloth = clmd->clothObject;
+ ClothSpring *spring = NULL;
+
+ if(cloth)
+ {
+ // TODO: look if this spring is already there
+
+ spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+ spring->ij = indexA;
+ spring->kl = indexB;
+ spring->restlen = restlength;
+ spring->type = spring_type;
+ spring->flags = 0;
+
+ cloth->numsprings++;
+
+ BLI_linklist_append ( &cloth->springs, spring );
+
+ return 1;
+ }
+ return 0;
+}
+
+int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm )
+{
+ ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL;
+ unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0;
++ unsigned int i = 0, j = 0;
+ unsigned int numverts = dm->getNumVerts ( dm );
+ unsigned int numedges = dm->getNumEdges ( dm );
+ unsigned int numfaces = dm->getNumFaces ( dm );
+ MEdge *medge = CDDM_get_edges ( dm );
+ MFace *mface = CDDM_get_faces ( dm );
+ unsigned int index2 = 0; // our second vertex index
+ LinkNode **edgelist = NULL;
+ EdgeHash *edgehash = NULL;
+ LinkNode *search = NULL, *search2 = NULL;
+ float temp[3];
+ LinkNode *node = NULL, *node2 = NULL;
+
+ // error handling
+ if ( numedges==0 )
+ return 0;
+
+ cloth->springs = NULL;
+
+ edgelist = MEM_callocN ( sizeof ( LinkNode * ) * numverts, "cloth_edgelist_alloc" );
+ for ( i = 0; i < numverts; i++ )
+ {
+ edgelist[i] = NULL;
+ }
+
+ if ( cloth->springs )
+ MEM_freeN ( cloth->springs );
+
+ // create spring network hash
+ edgehash = BLI_edgehash_new();
+
+ // structural springs
+ for ( i = 0; i < numedges; i++ )
+ {
+ spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+ if ( spring )
+ {
+ spring->ij = medge[i].v1;
+ spring->kl = medge[i].v2;
+ VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] );
+ spring->restlen = sqrt ( INPR ( temp, temp ) );
+ spring->type = CLOTH_SPRING_TYPE_STRUCTURAL;
+ spring->flags = 0;
+ struct_springs++;
+
+ if(!i)
+ node2 = BLI_linklist_append_fast ( &cloth->springs, spring );
+ else
+ node2 = BLI_linklist_append_fast ( &node->next, spring );
+ node = node2;
+ }
+ }
+
++ // calc collision balls *slow*
++ // better: use precalculated list with O(1) index access to all springs of a vertex
++ // missing for structural since it's not needed for building bending springs
++ /*
++ for ( i = 0; i < numverts; i++ )
++ {
++ search = cloth->springs;
++ for ( j = 0; j < struct_springs; j++ )
++ {
++ if ( !search )
++ break;
++
++ tspring = search->link;
++
++ if((tspring->ij == i) || (tspring->kl == i))
++ {
++ akku += bs->len;
++ akku_count++,
++ min = MIN2(bs->len,min);
++ max = MAX2(bs->len,max);
++ }
++ }
++ }
++ */
+ // shear springs
+ for ( i = 0; i < numfaces; i++ )
+ {
+ spring = ( ClothSpring *) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+ spring->ij = mface[i].v1;
+ spring->kl = mface[i].v3;
+ VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] );
+ spring->restlen = sqrt ( INPR ( temp, temp ) );
+ spring->type = CLOTH_SPRING_TYPE_SHEAR;
+
+ BLI_linklist_append ( &edgelist[spring->ij], spring );
+ BLI_linklist_append ( &edgelist[spring->kl], spring );
+ shear_springs++;
+
+ node2 = BLI_linklist_append_fast ( &node->next, spring );
+ node = node2;
+
+ if ( mface[i].v4 )
+ {
+ spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+ spring->ij = mface[i].v2;
+ spring->kl = mface[i].v4;
+ VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] );
+ spring->restlen = sqrt ( INPR ( temp, temp ) );
+ spring->type = CLOTH_SPRING_TYPE_SHEAR;
+
+ BLI_linklist_append ( &edgelist[spring->ij], spring );
+ BLI_linklist_append ( &edgelist[spring->kl], spring );
+ shear_springs++;
+
+ node2 = BLI_linklist_append_fast ( &node->next, spring );
+ node = node2;
+ }
+ }
+
+ // bending springs
+ search2 = cloth->springs;
+ for ( i = struct_springs; i < struct_springs+shear_springs; i++ )
+ {
+ if ( !search2 )
+ break;
+
+ tspring2 = search2->link;
+ search = edgelist[tspring2->kl];
+ while ( search )
+ {
+ tspring = search->link;
+ index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) );
+
+ // check for existing spring
+ // check also if startpoint is equal to endpoint
+ if ( !BLI_edgehash_haskey ( edgehash, index2, tspring2->ij )
+ && !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 )
+ && ( index2!=tspring2->ij ) )
+ {
+ spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+ spring->ij = tspring2->ij;
+ spring->kl = index2;
+ VECSUB ( temp, cloth->x[index2], cloth->x[tspring2->ij] );
+ spring->restlen = sqrt ( INPR ( temp, temp ) );
+ spring->type = CLOTH_SPRING_TYPE_BENDING;
+ BLI_edgehash_insert ( edgehash, spring->ij, index2, NULL );
+ bend_springs++;
+
+ node2 = BLI_linklist_append_fast ( &node->next, spring );
+ node = node2;
+ }
+ search = search->next;
+ }
+ search2 = search2->next;
+ }
+
+ cloth->numspringssave = cloth->numsprings = struct_springs + shear_springs + bend_springs;
+ cloth->numothersprings = struct_springs + shear_springs;
+
+ for ( i = 0; i < numverts; i++ )
+ {
+ BLI_linklist_free ( edgelist[i],NULL );
+ }
+ if ( edgelist )
+ MEM_freeN ( edgelist );
+
+ cloth->edgehash = edgehash;
+
+ return 1;
+
+} /* cloth_build_springs */
+/***************************************************************************************
+* SPRING NETWORK BUILDING IMPLEMENTATION END
+***************************************************************************************/
+
#include "BKE_main.h"
#include "BKE_anim.h"
#include "BKE_bad_level_calls.h"
+#include "BKE_collisions.h"
+ #include "BKE_curve.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
- #include "BKE_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
#include "BKE_booleanops.h"
#include "BKE_object.h"
#include "BKE_mesh.h"
#include "BKE_softbody.h"
+#include "BKE_cloth.h"
#include "BKE_material.h"
+ #include "BKE_particle.h"
+ #include "BKE_pointcache.h"
+ #include "BKE_utildefines.h"
#include "depsgraph_private.h"
#include "LOD_DependKludge.h"
return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
}
+ClothModifierData *modifiers_isClothEnabled(Object *ob)
+{
+ ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+
+ return clmd;
+}
+
+ int modifiers_isParticleEnabled(Object *ob)
+ {
+ ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem);
+
+ return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
+ }
+
LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask)
{
LinkNode *dataMasks = NULL;
sb->bpoint= NULL; // init pointers so it gets rebuilt nicely
sb->bspring= NULL;
sb->scratch= NULL;
-
-
+ /* although not used anymore */
+ /* still have to be loaded to be compatible with old files */
sb->keys= newdataadr(fd, sb->keys);
test_pointer_array(fd, (void **)&sb->keys);
if(sb->keys) {
#define B_GROUP_RELINK 1460
#define B_OBJECT_IPOFLAG 1461
+ #define B_BAKEABLE_CHANGE 1470
- #define B_CLOTH_CLEARCACHEALL 1470
- #define B_CLOTH_CLEARCACHEFRAME 1471
- #define B_CLOTH_CHANGEPREROLL 1472
- #define B_CLOTH_DEL_VG 1473
- #define B_CLOTH_RENEW 1474
+/* Cloth sim button defines */
++#define B_CLOTH_CLEARCACHEALL 1480
++#define B_CLOTH_CLEARCACHEFRAME 1481
++#define B_CLOTH_CHANGEPREROLL 1482
++#define B_CLOTH_DEL_VG 1483
++#define B_CLOTH_RENEW 1484
+
/* *********************** */
#define B_WORLDBUTS 1600
eModifierType_Smooth,
eModifierType_Cast,
eModifierType_MeshDeform,
- eModifierType_PointCache,
+ eModifierType_ParticleSystem,
+ eModifierType_ParticleInstance,
+ eModifierType_Explode,
+ eModifierType_Cloth,
- eModifierType_Collision,
++ eModifierType_Collision,
NUM_MODIFIER_TYPES
} ModifierType;
"DNA_color_types.h",
"DNA_brush_types.h",
"DNA_customdata_types.h",
+ "DNA_particle_types.h",
+ "DNA_cloth_types.h",
// if you add files here, please add them at the end
// of makesdna.c (this file) as well
#include "DNA_color_types.h"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
+ #include "DNA_particle_types.h"
+#include "DNA_cloth_types.h"
/* end of list */
ModifierTypeInfo *mti = modifierType_getInfo(i);
/* Only allow adding through appropriate other interfaces */
- if(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue;
+ if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
+
+ if(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue;
if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
(ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
if(hmd->indexar==NULL)
height += 20;
} else if (md->type==eModifierType_Softbody) {
- height = 26;
+ height = 31;
+ } else if (md->type==eModifierType_Cloth) {
+ height = 26;
+ } else if (md->type==eModifierType_Collision) {
+ height = 19;
} else if (md->type==eModifierType_Boolean) {
height = 48;
} else if (md->type==eModifierType_Array) {
} else if (md->type==eModifierType_MeshDeform) {
MeshDeformModifierData *mmd= (MeshDeformModifierData*)md;
height = (mmd->bindcos)? 73: 93;
- } else if (md->type==eModifierType_PointCache) {
- height = 48;
- }
-
+ } else if (md->type==eModifierType_ParticleSystem) {
+ height = 31;
+ } else if (md->type==eModifierType_ParticleInstance) {
+ height = 94;
+ } else if (md->type==eModifierType_Explode) {
+ height = 94;
+ }
-
/* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, "");
y -= 18;
- if (!isVirtual) {
+ if (!isVirtual && (md->type!=eModifierType_Collision)) {
uiBlockBeginAlign(block);
- but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
- uiButSetFunc(but, modifiers_applyModifier, ob, md);
- if ((md->type!=eModifierType_Softbody) && (md->type!=eModifierType_Cloth)) {
+ if (md->type==eModifierType_ParticleSystem) {
+ but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object");
+ uiButSetFunc(but, modifiers_convertParticles, ob, md);
+ }
+ else{
+ but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
+ uiButSetFunc(but, modifiers_applyModifier, ob, md);
+ }
+
- if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem) {
++ if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
uiButSetFunc(but, modifiers_copyModifier, ob, md);
}
#include "DNA_scene_types.h"
#include "BKE_action.h"
++#include "BKE_cloth.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_library.h"
#endif // DISABLE_ELBEEM
}
++/* Panel for cloth */
++static void object_cloth__enabletoggle(void *ob_v, void *arg2)
++{
++ Object *ob = ob_v;
++ ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
++
++ if (!md) {
++ md = modifier_new(eModifierType_Cloth);
++ BLI_addhead(&ob->modifiers, md);
++ }
++ else {
++ BLI_remlink(&ob->modifiers, md);
++ modifier_free(md);
++ }
++
++ allqueue(REDRAWBUTSEDIT, 0);
++}
++
++static void object_panel_cloth(Object *ob)
++{
++ uiBlock *block;
++ static int val, val2;
++ uiBut *but;
++ ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
++ block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth", UI_EMBOSS, UI_HELV, curarea->win);
++ if(uiNewPanel(curarea, block, "Cloth", "Physics", 640, 0, 318, 204)==0) return;
++
++ if(ob->id.lib) uiSetButLock(1, "Can't edit library data");
++ val = ((clmd)?(1):(0));
++
++ but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Cloth Object", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become cloth");
++ uiButSetFunc(but, object_cloth__enabletoggle, ob, NULL);
++ uiDefBut(block, LABEL, 0, "",10,10,300,0, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/
++
++ if(clmd)
++ {
++ // but = uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object", 170,200,130,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Sets object to become a cloth collision object");
++
++ if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ))
++ {
++ Cloth *cloth = clmd->clothObject;
++ int defCount;
++ char *clvg1, *clvg2;
++ char clmvg [] = "Mass Vertex Group%t|None%x0|";
++
++ val2=0;
++
++ // uiDefButBitI(block, TOG, CSIMSETT_FLAG_ADVANCED, REDRAWBUTSOBJECT, "Advanced", 180,200,130,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Enable advanced mode");
++
++ /* GENERAL STUFF */
++ uiClearButLock();
++ uiBlockBeginAlign(block);
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,170,150,20, &clmd->sim_parms->structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure");
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,170,150,20, &clmd->sim_parms->bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility");
++ uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms->stepsPerFrame, 3.0, 10.0, 5, 0, "Quality of the simulation (higher=>better=>slower)");
++ uiBlockEndAlign(block);
++ uiBlockBeginAlign(block);
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 160,150,150,20, &clmd->sim_parms->Cdis, 0.0, 10.0, 10, 0, "Spring damping");
++ uiDefButF(block, NUM, B_DIFF, "Air Damp:", 10,130,150,20, &clmd->sim_parms->Cvi, 0.0, 10.0, 10, 0, "Apply gravitation to point movement");
++ uiBlockEndAlign(block);
++
++ uiClearButLock();
++
++ uiBlockBeginAlign(block);
++ uiDefBut(block, LABEL, 0, "Gravity:", 10,100,60,20, NULL, 0.0, 0, 0, 0, "");
++ // uiClearButLock();
++
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,100,80,20, &clmd->sim_parms->gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement");
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,100,80,20, &clmd->sim_parms->gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement");
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,100,80,20, &clmd->sim_parms->gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement");
++ uiBlockEndAlign(block);
++
++ /* GOAL STUFF */
++ uiBlockBeginAlign(block);
++ uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position");
++ if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL)
++ {
++ if(ob->type==OB_MESH)
++ {
++
++ defCount = sizeof (clmvg);
++ clvg1 = get_vertexgroup_menustr (ob);
++ clvg2 = MEM_callocN (strlen (clvg1) + 1 + defCount, "clothVgMS");
++ if (! clvg2) {
++ printf ("draw_modifier: error allocating memory for cloth vertex group menu string.\n");
++ return;
++ }
++ defCount = BLI_countlist (&ob->defbase);
++ if (defCount == 0)
++ {
++ clmd->sim_parms->vgroup_mass = 0;
++ }
++ sprintf (clvg2, "%s%s", clmvg, clvg1);
++
++ uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 140,70,20,20, &clmd->sim_parms->vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups");
++ MEM_freeN (clvg1);
++ MEM_freeN (clvg2);
++
++ if(clmd->sim_parms->vgroup_mass)
++ {
++ bDeformGroup *defGroup = BLI_findlink(&ob->defbase, clmd->sim_parms->vgroup_mass-1);
++ if(defGroup)
++ uiDefBut(block, BUT, B_DIFF, defGroup->name, 160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group");
++ else
++ uiDefBut(block, BUT, B_DIFF, "(no group)", 160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore");
++
++ uiDefIconBut(block, BUT, B_CLOTH_DEL_VG, ICON_X, 290,70,20,20, 0, 0, 0, 0, 0, "Disable use of vertex group");
++
++ }
++ else
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used");
++
++ }
++ else
++ {
++ uiDefButS(block, TOG, B_CLOTH_RENEW, "W", 140,70,20,20, &clmd->sim_parms->vgroup_mass, 0, 1, 0, 0, "Use control point weight values");
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:", 160,70,150,20, &clmd->sim_parms->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used");
++ }
++
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "G Stiff:", 10,50,150,20, &clmd->sim_parms->goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness");
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms->goalfrict, 0.0, 50.0, 10, 0, "Goal (vertex target position) friction");
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:", 10,30,150,20, &clmd->sim_parms->mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range");
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:", 160,30,150,20, &clmd->sim_parms->maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range");
++ }
++ uiBlockEndAlign(block);
++
++ /*
++ // no tearing supported anymore since modifier stack restrictions
++ uiBlockBeginAlign(block);
++ uiDefButBitI(block, TOG, CSIMSETT_FLAG_TEARING_ENABLED, B_EFFECT_DEP, "Tearing", 10,0,150,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Sets object to become a cloth collision object");
++
++ if (clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)
++ {
++ uiDefButI(block, NUM, B_DIFF, "Max extent:", 160,0,150,20, &clmd->sim_parms->maxspringlen, 1.0, 1000.0, 10, 0, "Maximum extension before spring gets cut");
++ }
++
++ uiBlockEndAlign(block);
++ */
++ }
++ }
++}
++
++
++static void object_panel_cloth_II(Object *ob)
++{
++ uiBlock *block;
++ static int val;
++ uiBut *but;
++ ClothModifierData *clmd = NULL;
++
++ clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
++ if(clmd)
++ {
++ if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ))
++ {
++ Cloth *cloth = clmd->clothObject;
++ char str[128];
++
++ block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_II", UI_EMBOSS, UI_HELV, curarea->win);
++ uiNewPanelTabbed("Cloth", "Physics");
++ if(uiNewPanel(curarea, block, "Cloth Cache", "Physics", 651, 0, 318, 204)==0) return;
++
++ uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
++
++ uiDefButI(block, NUM, B_DIFF, "First Frame:", 10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts");
++ uiDefButI(block, NUM, B_DIFF, "Last Frame:", 160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops");
++ /*
++ if(clmd->sim_parms->cache)
++ {
++ int length = BLI_linklist_length(clmd->sim_parms->cache);
++
++ // correct spelling if only 1 frame cacheed --> only gimmick
++ if(length-clmd->sim_parms->preroll>1)
++ sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length);
++ else
++ sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms->preroll, clmd->sim_parms->preroll, length);
++
++ uiDefBut(block, LABEL, 0, str, 10,140,290,20, NULL, 0.0, 0, 0, 0, "");
++ uiDefBut(block, LABEL, 0, "Clear cache:", 10,120,290,20, NULL, 0.0, 0, 0, 0, "");
++ uiBlockBeginAlign (block);
++ uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll");
++ uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache");
++ if(length>1) // B_CLOTH_CHANGEPREROLL
++ uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms->preroll, 0, length-1, 1, 0, "Simulation starts on this frame");
++ else
++ uiDefBut(block, LABEL, 0, " ", 10,80,145,20, NULL, 0.0, 0, 0, 0, "");
++ }
++ else
++ {
++ uiDefBut(block, LABEL, 0, "No frames cached.", 10,120,290,20, NULL, 0.0, 0, 0, 0, "");
++ }*/
++ uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache", 10,50,145,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed");
++ uiBlockEndAlign(block);
++ }
++ }
++ // uiBlockEndAlign(block);
++}
++
++static void object_panel_cloth_III(Object *ob)
++{
++ uiBlock *block;
++ ClothModifierData *clmd = NULL;
++
++ clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
++ if(clmd)
++ {
++ block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_III", UI_EMBOSS, UI_HELV, curarea->win);
++ uiNewPanelTabbed("Cloth", "Physics");
++ if(uiNewPanel(curarea, block, "Cloth Collisions", "Physics", 651, 0, 318, 204)==0) return;
++
++ uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
++
++ uiBlockBeginAlign(block);
++ uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions", 10,160,130,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable collisions with this object");
++ if (clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED)
++ {
++ // uiDefBut(block, LABEL, 0, "",10,10,300,20, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 10,140,150,20, &clmd->coll_parms->epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in");
++ uiDefBut(block, LABEL, 0, "",160,140,150,20, NULL, 0.0, 0, 0, 0, "");
++ uiDefButF(block, NUM, B_CLOTH_RENEW, "Selfcoll balls:", 10,120,150,20, &clmd->coll_parms->selfepsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between two selfcollision points");
++ }
++ else
++ uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, "");
++ uiBlockEndAlign(block);
++ }
++}
++
void object_panels()
{
Object *ob;
/* check context here */
ob= OBACT;
if(ob) {
+ if(ob->type==OB_MESH)
+ object_panel_deflection(ob);
object_panel_fields(ob);
- object_panel_particles(ob);
- object_panel_particles_motion(ob);
object_softbodies(ob);
object_softbodies_II(ob);
+ object_panel_cloth(ob);
+ object_panel_cloth_II(ob);
+ object_panel_cloth_III(ob);
object_panel_fluidsim(ob);
}
}
allqueue(REDRAWBUTSEDIT, 0);
}
+ else if(G.f & G_PARTICLEEDIT) {
+ ;
+ }
else {
base= FIRSTBASE;
- while (base) {
-
+
+ while (base) {
+
if(base->flag & BA_DO_IPO) redrawipo= 1;
ob= base->object;