diff options
-rw-r--r-- | CMakeLists.txt | 23 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_cloth.h | 188 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_modifier.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/cloth.c | 1653 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/collision.c | 900 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/implicit.c | 1194 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 221 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 5 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_cloth_types.h | 102 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 6 | ||||
-rw-r--r-- | source/blender/src/buttons_object.c | 189 | ||||
-rw-r--r-- | source/blender/src/drawobject.c | 106 | ||||
-rw-r--r-- | source/blender/src/vpaint.c | 7 |
14 files changed, 2031 insertions, 2567 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d79c2220104..4eb5e9c659d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,8 +65,9 @@ OPTION(WITH_ELBEEM "Enable Elbeem (Fluid Simulation)" ON) OPTION(WITH_QUICKTIME "Enable Quicktime Support" OFF) OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" OFF) OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) -OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) -OPTION(YESIAMSTUPID "Enable execution on 64-bit platforms" OFF) +OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) +OPTION(YESIAMSTUPID "Enable execution on 64-bit platforms" OFF) +OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF) IF(NOT WITH_GAMEENGINE AND WITH_PLAYER) MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE") @@ -184,6 +185,13 @@ IF(UNIX) SET(LLIBS "-lXi -lutil -lc -lm -lpthread -lstdc++") + IF(WITH_OPENMP) + SET(LLIBS "${LLIBS} -lgomp ") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ") + ENDIF(WITH_OPENMP) + + SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -DXP_UNIX -Wno-char-subscripts") SET(PLATFORM_LINKFLAGS "-pthread") @@ -270,6 +278,11 @@ IF(WIN32) SET(CMAKE_C_FLAGS_MINSIZEREL "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE) SET(CMAKE_C_FLAGS_RELWITHDEBINFO "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE) + IF(WITH_OPENMP) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /openmp ") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp ") + ENDIF(WITH_OPENMP) + SET(SDL ${LIBDIR}/sdl) SET(SDL_INC ${SDL}/include) SET(SDL_LIB SDL) @@ -347,6 +360,12 @@ IF(APPLE) SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing") SET(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") + IF(WITH_OPENMP) + SET(LLIBS "${LLIBS} -lgomp ") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ") + ENDIF(WITH_OPENMP) + SET(SDL ${LIBDIR}/sdl) SET(SDL_INC ${SDL}/include) SET(SDL_LIB SDL) diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index b122347998d..eb1f33ae600 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -34,14 +34,14 @@ #ifndef BKE_CLOTH_H #define BKE_CLOTH_H -#include "BKE_customdata.h" #include "BLI_linklist.h" +#include "BKE_customdata.h" #include "BKE_DerivedMesh.h" -#include "BKE_object.h" - #include "DNA_cloth_types.h" #include "DNA_customdata_types.h" #include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" struct Object; struct Cloth; @@ -49,8 +49,8 @@ struct MFace; struct DerivedMesh; struct ClothModifierData; -// this is needed for inlining behaviour +// this is needed for inlining behaviour #ifndef _WIN32 #define LINUX #define DO_INLINE inline @@ -60,71 +60,6 @@ struct ClothModifierData; #define CLOTH_MAX_THREAD 2 -typedef struct fc -{ - float *d, *d0; // density - float *T, *T0; // temperature - float *u, *u0; // velocity in x direction - float *v, *v0; // velocity in y direction - float *w, *w0; // velocity in z direction - unsigned char* _texture_data; - float _light_dir[3]; - int _ray_templ[4096][3]; - FILE* _fp; - int _cur_frame; - int _nframes; -} fc; -fc *f_init(void); -void f_free(fc *m_fc); -void step(fc *m_fc, float dt); - - -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; - char octantflag; - float weight; -} ClothVertex; - -typedef struct ClothSpring { - unsigned int ij; /* Pij from the paper, one end of the spring. */ - unsigned int kl; /* Pkl from the paper, one end of the spring. */ - float restlen; /* The original length of the spring. */ - unsigned 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]; - struct fc *m_fc; -} Cloth; /* goal defines */ #define SOFTGOALSNAP 0.999f @@ -155,9 +90,7 @@ typedef enum 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_FLAG_CCACHE_PROTECT = ( 1 << 5 ), // true if tearing is enabled } CLOTH_SIMSETTINGS_FLAGS; /* SPRING FLAGS */ @@ -172,7 +105,6 @@ typedef enum CLOTH_SPRING_TYPE_STRUCTURAL = 0, CLOTH_SPRING_TYPE_SHEAR, CLOTH_SPRING_TYPE_BENDING, - CLOTH_SPRING_TYPE_COLLISION, } CLOTH_SPRING_TYPES; /* SPRING FLAGS */ @@ -188,32 +120,91 @@ typedef enum // needed for buttons_object.c -void cloth_clear_cache(struct Object *ob, struct ClothModifierData *clmd, float framenr); -void cloth_free_modifier ( struct ClothModifierData *clmd ); +void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr); // needed for cloth.c -void implicit_set_positions ( struct ClothModifierData *clmd ); +void implicit_set_positions ( ClothModifierData *clmd ); // from cloth.c, needed for modifier.c -DerivedMesh *clothModifier_do(struct ClothModifierData *clmd, struct Object *ob, struct DerivedMesh *dm, int useRenderParams, int isFinalCalc); +void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, float ( *vertexCos ) [3], int numverts ); + +// used in collision.c +typedef struct Tree +{ + struct Tree *nodes[4]; // 4 children --> quad-tree + struct Tree *parent; + struct Tree *nextLeaf; + struct Tree *prevLeaf; + float bv[26]; // Bounding volume of all nodes / we have 7 axes on a 14-DOP + unsigned int tri_index; // this saves the index of the face + int count_nodes; // how many nodes are used + int traversed; // how many nodes already traversed until this level? + int isleaf; +} +Tree; + +typedef struct Tree TreeNode; + +typedef struct BVH +{ + unsigned int numfaces; + unsigned int numverts; + ClothVertex *verts; // just a pointer to the original datastructure + MFace *mfaces; // just a pointer to the original datastructure + struct LinkNode *tree; + TreeNode *root; // TODO: saving the root --> is this really needed? YES! + TreeNode *leaf_tree; /* Tail of the leaf linked list. */ + TreeNode *leaf_root; /* Head of the leaf linked list. */ + float epsilon; /* epslion is used for inflation of the k-dop */ + int flags; /* bvhFlags */ +} +BVH; + +typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 ); + + +///////////////////////////////////////////////// +// collision.c +//////////////////////////////////////////////// -// needed in implicit.c -int cloth_bvh_objcollision(struct ClothModifierData *clmd, float step, float prevstep, float dt); +// needed for implicit.c +void bvh_collision_response ( ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree * tree1, Tree * tree2 ); +int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt ); //////////////////////////////////////////////// ///////////////////////////////////////////////// +// kdop.c +//////////////////////////////////////////////// + +// needed for cloth.c +void bvh_free ( BVH * bvh ); +BVH *bvh_build ( ClothModifierData *clmd, float epsilon ); +LinkNode *BLI_linklist_append_fast ( LinkNode **listp, void *ptr ); + +// needed for collision.c +int bvh_traverse ( ClothModifierData * clmd, ClothModifierData * coll_clmd, Tree * tree1, Tree * tree2, float step, CM_COLLISION_RESPONSE collision_response ); +void bvh_update ( ClothModifierData * clmd, BVH * bvh, int moving ); + +//////////////////////////////////////////////// + + + +///////////////////////////////////////////////// // cloth.c //////////////////////////////////////////////// -void cloth_free_modifier ( struct ClothModifierData *clmd ); -void cloth_init ( struct ClothModifierData *clmd ); +void cloth_free_modifier ( ClothModifierData *clmd ); +void cloth_init ( ClothModifierData *clmd ); +void cloth_deform_verts ( struct Object *ob, float framenr, float ( *vertexCos ) [3], int numVerts, void *derivedData, ClothModifierData *clmd ); +void cloth_update_normals ( ClothVertex *verts, int nVerts, MFace *face, int totface ); + //////////////////////////////////////////////// /* Typedefs for function pointers we need for solvers and collision detection. */ -typedef void ( *CM_COLLISION_SELF ) ( struct ClothModifierData *clmd, int step ); -// typedef void ( *CM_COLLISION_OBJ ) ( ClothModifierData *clmd, int step, CM_COLLISION_RESPONSE collision_response ); +typedef void ( *CM_COLLISION_SELF ) ( 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. */ @@ -229,26 +220,29 @@ typedef struct { char *name; CM_SOLVER_ID id; - 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 ); + int ( *init ) ( Object *ob, ClothModifierData *clmd ); + int ( *solver ) ( Object *ob, float framenr, ClothModifierData *clmd, ListBase *effectors ); + int ( *free ) ( ClothModifierData *clmd ); } CM_SOLVER_DEF; /* new C implicit simulator */ -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 ); +int implicit_init ( Object *ob, ClothModifierData *clmd ); +int implicit_free ( ClothModifierData *clmd ); +int implicit_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors ); +/* used for caching in implicit.c */ +typedef struct Frame +{ + ClothVertex *verts; + ClothSpring *springs; + unsigned int numverts, numsprings; + float time; /* we need float since we want to support sub-frames */ +} +Frame; /* used for collisions in collision.c */ -/* typedef struct CollPair { unsigned int face1; // cloth face @@ -263,7 +257,6 @@ typedef struct CollPair unsigned int pointsb[4]; } CollPair; -*/ /* used for collisions in collision.c */ typedef struct EdgeCollPair @@ -289,8 +282,5 @@ typedef struct FaceCollPair } FaceCollPair; -// function definitions from implicit.c -DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar); - #endif diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 8927584de1b..682eb1a00dd 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -287,7 +287,7 @@ int modifiers_getCageIndex(struct Object *ob, int *lastPossibleCageIndex_r); int modifiers_isSoftbodyEnabled(struct Object *ob); -struct ClothModifierData *modifiers_isClothEnabled(Object *ob); +ModifierData * modifiers_isClothEnabled(Object *ob); int modifiers_isParticleEnabled(struct Object *ob); struct Object *modifiers_isDeformedByArmature(struct Object *ob); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 318d6eac410..fef932174a1 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -39,15 +39,15 @@ /* types */ #include "DNA_curve_types.h" -#include "DNA_cloth_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" +#include "DNA_cloth_types.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_lattice_types.h" #include "DNA_scene_types.h" +#include "DNA_modifier_types.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -55,8 +55,6 @@ #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" @@ -65,11 +63,11 @@ #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_cloth.h" +#include "BKE_modifier.h" #include "BKE_utildefines.h" - +#include "BKE_DerivedMesh.h" #include "BIF_editdeform.h" #include "BIF_editkey.h" #include "DNA_screen_types.h" @@ -78,21 +76,7 @@ #include "BIF_space.h" #include "mydevice.h" -#ifdef WIN32 -#include <windows.h> -#endif // WIN32 -#ifdef __APPLE__ -#define GL_GLEXT_LEGACY 1 -#include <OpenGL/gl.h> -#include <OpenGL/glu.h> -#else -#include <GL/gl.h> -#if defined(__sun__) && !defined(__sparc__) -#include <mesa/glu.h> -#else -#include <GL/glu.h> -#endif -#endif +#include "BKE_pointcache.h" #ifdef _WIN32 void tstart ( void ) @@ -106,9 +90,9 @@ double tval() } #else #include <sys/time.h> - static struct timeval _tstart, _tend; - static struct timezone tz; - void tstart ( void ) +static struct timeval _tstart, _tend; +static struct timezone tz; +void tstart ( void ) { gettimeofday ( &_tstart, &tz ); } @@ -128,82 +112,88 @@ double tval() /* 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 }, -}; +static CM_SOLVER_DEF solvers [] = + { + { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free }, + // { "Implicit C++", CM_IMPLICITCPP, implicitcpp_init, implicitcpp_solver, implicitcpp_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); +static void cloth_to_object ( Object *ob, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ); +static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); +static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts, float framenr ); +static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ); +int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ); +static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup ); + -int cloth_build_springs ( ClothModifierData *clmd, 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) +* 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.49; - + 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->sim_parms.firstframe = 1; + clmd->sim_parms.lastframe = 250; + clmd->coll_parms.self_friction = 5.0; + clmd->coll_parms.friction = 10.0; + clmd->coll_parms.loop_count = 1; + clmd->coll_parms.epsilon = 0.01f; + clmd->coll_parms.flags = 0; + /* 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; + 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; + clmd->sim_parms.maxgoal = 1.0f; + clmd->sim_parms.mingoal = 0.0f; + clmd->sim_parms.defgoal = 0.7f; + clmd->sim_parms.goalspring = 100.0f; + clmd->sim_parms.goalfrict = 0.0f; + + clmd->sim_parms.cache = NULL; } // unused in the moment, cloth needs quads from mesh -DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) +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); + 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 *mvert = CDDM_get_verts ( dm ); + MEdge *medge = CDDM_get_edges ( dm ); + MFace *mface = CDDM_get_faces ( dm ); MVert *mvert2; MFace *mface2; @@ -215,121 +205,118 @@ DerivedMesh *CDDM_convert_to_triangle(DerivedMesh *dm) float vec1[3], vec2[3], vec3[3], vec4[3], vec5[3]; float mag1=0, mag2=0; - for(i = 0; i < numfaces; i++) + for ( i = 0; i < numfaces; i++ ) { - if(mface[i].v4) - numquads++; - else - numtris++; -} + if ( mface[i].v4 ) + numquads++; + else + numtris++; + } - result = CDDM_from_template(dm, numverts, 0, numtris + 2*numquads); + result = CDDM_from_template ( dm, numverts, 0, numtris + 2*numquads ); - if(!result) - return NULL; + if ( !result ) + return NULL; // do verts - mvert2 = CDDM_get_verts(result); - for(a=0; a<numverts; a++) + mvert2 = CDDM_get_verts ( result ); + for ( a=0; a<numverts; a++ ) { - MVert *inMV; - MVert *mv = &mvert2[a]; + MVert *inMV; + MVert *mv = &mvert2[a]; - inMV = &mvert[a]; + inMV = &mvert[a]; - DM_copy_vert_data(dm, result, a, a, 1); - *mv = *inMV; -} + 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++) + mface2 = CDDM_get_faces ( result ); + for ( a=0, i=0; a<numfaces; a++ ) { - MFace *mf = &mface2[i]; - MFace *inMF; - inMF = &mface[a]; + MFace *mf = &mface2[i]; + MFace *inMF; + inMF = &mface[a]; - - // DM_copy_face_data(dm, result, a, i, 1); + /* + DM_copy_face_data(dm, result, a, i, 1); - // *mf = *inMF; - + *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; -} + 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; + mf->v4 = 0; + mf->flag |= ME_SMOOTH; - test_index_face(mf, NULL, 0, 3); + test_index_face ( mf, NULL, 0, 3 ); - if(mface[a].v4) - { - MFace *mf2; + if ( mface[a].v4 ) + { + MFace *mf2; - i++; + i++; - mf2 = &mface2[i]; - - // DM_copy_face_data(dm, result, a, i, 1); + mf2 = &mface2[i]; + /* + DM_copy_face_data(dm, result, a, i, 1); - // *mf2 = *inMF; - + *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; + 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); -} + test_index_face ( mf2, NULL, 0, 3 ); + } - i++; -} + i++; + } - CDDM_calc_edges(result); - CDDM_calc_normals(result); + CDDM_calc_edges ( result ); + CDDM_calc_normals ( result ); return result; - */ - - return NULL; + } -DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) +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); + 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 *mvert = CDDM_get_verts ( dm ); + MEdge *medge = CDDM_get_edges ( dm ); + MFace *mface = CDDM_get_faces ( dm ); MVert *mvert2; MFace *mface2; @@ -339,91 +326,90 @@ DerivedMesh *CDDM_create_tearing(ClothModifierData *clmd, DerivedMesh *dm) 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))) + + for ( i = 0; i < numsprings; i++ ) { - BLI_edgehash_insert(edgehash, springs[i].ij, springs[i].kl, NULL); - BLI_edgehash_insert(edgehash, springs[i].kl, springs[i].ij, NULL); - j++; -} -} - + if ( ( springs[i].flags & CLOTH_SPRING_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; + 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++) + mvert2 = CDDM_get_verts ( result ); + for ( a=0; a<numverts; a++ ) { - MVert *inMV; - MVert *mv = &mvert2[a]; + MVert *inMV; + MVert *mv = &mvert2[a]; - inMV = &mvert[a]; + inMV = &mvert[a]; - DM_copy_vert_data(dm, result, a, a, 1); - *mv = *inMV; -} + 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++) + mface2 = CDDM_get_faces ( result ); + for ( a=0, i=0; a<numfaces; a++ ) { - MFace *mf = &mface2[i]; - MFace *inMF; - inMF = &mface[a]; + MFace *mf = &mface2[i]; + MFace *inMF; + inMF = &mface[a]; - - // DM_copy_face_data(dm, result, a, i, 1); + /* + 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++; -} -} + *mf = *inMF; + */ - CDDM_lower_num_faces(result, i); - CDDM_calc_edges(result); - CDDM_calc_normals(result); - - BLI_edgehash_free(edgehash, NULL); + 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)) + if(!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) { stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); @@ -447,9 +433,9 @@ static void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr 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); + fwrite(&cloth->verts[a].x, sizeof(float),4,fp); + fwrite(&cloth->verts[a].xconst, sizeof(float),4,fp); + fwrite(&cloth->verts[a].v, sizeof(float),4,fp); } fclose(fp); @@ -472,17 +458,17 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) else { for(a = 0; a < cloth->numverts; a++) { - if(fread(&cloth->x[a], sizeof(float), 4, fp) != 4) + if(fread(&cloth->verts[a].x, sizeof(float), 4, fp) != 4) { ret = 0; break; } - if(fread(&cloth->xconst[a], sizeof(float), 4, fp) != 4) + if(fread(&cloth->verts[a].xconst, sizeof(float), 4, fp) != 4) { ret = 0; break; } - if(fread(&cloth->v[a], sizeof(float), 4, fp) != 4) + if(fread(&cloth->verts[a].v, sizeof(float), 4, fp) != 4) { ret = 0; break; @@ -492,182 +478,200 @@ static int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) fclose(fp); } - if(clmd->sim_parms->solver_type == 0) + if(clmd->sim_parms.solver_type == 0) implicit_set_positions(clmd); return ret; } -int m_fc_open(ClothModifierData *clmd) -{ - Cloth *cloth = clmd->clothObject; - int _N; - fc *m_fc = NULL; - - if(!cloth) - return 0; - - m_fc = cloth->m_fc; - - m_fc->_fp = fopen("/home/daniel/Desktop/f32rand.dat", "rb"); - if (!m_fc->_fp) - return 0; - - fread(&_N, sizeof(int), 1, m_fc->_fp); - fread(&_N, sizeof(int), 1, m_fc->_fp); - printf("Resolution: %dx%dx%d\n", _N, _N, _N); - - fread(&m_fc->_nframes, sizeof(int), 1, m_fc->_fp); - printf("Number of frames: %d\n", m_fc->_nframes); - m_fc->_cur_frame = 0; - - return 1; -} - - -/************************************************ - * clothModifier_do - main simulation function -************************************************/ -DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) +/** +* cloth_deform_verts - simulates one step, framenr is in frames. +* +**/ +void clothModifier_do ( ClothModifierData *clmd, Object *ob, DerivedMesh *dm, + float ( *vertexCos ) [3], int numverts ) { 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; + DerivedMesh *result = NULL, *result2 = 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; + unsigned int framenr = ( float ) G.scene->r.cfra; + float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); + ListBase *effectors = NULL; + ClothVertex *newframe= NULL, *verts; + Frame *frame = NULL; + LinkNode *search = NULL; + float deltaTime = current_time - clmd->sim_parms.sim_time; + + clmd->sim_parms.ob = ob; - 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 ) + if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) ) { - 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 ( 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, clmd, vertexCos, numverts ); + } + return; + } + 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, clmd, vertexCos, numverts ); + } + return; + } + 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, clmd, vertexCos, numverts ); + } + clmd->sim_parms.sim_time = current_time; + return; + } + } + + } + } + */ + + // unused in the moment, calculated seperately in implicit.c + clmd->sim_parms.dt = 1.0f / clmd->sim_parms.stepsPerFrame; + + clmd->sim_parms.sim_time = current_time; + + // check if cloth object was some collision object before and needs freeing now + if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) && ( clmd->clothObject != NULL ) && ( clmd->clothObject->old_solver_type == 255 ) ) { - if ( cloth_cache_search_frame ( clmd, framenr ) ) + // temporary set CSIMSETT_FLAG_COLLOBJ flag for proper freeing + clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + cloth_free_modifier ( clmd ); + clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + } + + // This is for collisions objects: check special case CSIMSETT_FLAG_COLLOBJ + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ ) { - 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) + // save next position + time + if ( ( clmd->clothObject == NULL ) || ( numverts != clmd->clothObject->numverts ) ) + { + if ( !collobj_from_object ( ob, clmd, dm, vertexCos, framenr ) ) + { + clmd->sim_parms.flags |= CLOTH_SIMSETTINGS_FLAG_COLLOBJ; + cloth_free_modifier ( clmd ); + return; + } + + if ( clmd->clothObject == NULL ) + return; + + cloth = clmd->clothObject; + } + + // Save old position + clmd->sim_parms.sim_time_old = clmd->sim_parms.sim_time; + clmd->sim_parms.sim_time = current_time; + + verts = cloth->verts; + + for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) + { + // Save the previous position. + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->txold, verts->x ); + + // Get the current position. + VECCOPY ( verts->x, vertexCos[i] ); + Mat4MulVecfl ( ob->obmat, verts->x ); + + // Compute the vertices "velocity". + // (no dt correction here because of float error) + VECSUB ( verts->v, verts->x, verts->xold ); + } + + return; + } + + if ( deltaTime == 1.0f ) { - if ((clmd->clothObject == NULL) || (numverts != clmd->clothObject->numverts) ) + 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 ( !cloth_from_object ( ob, clmd, dm, vertexCos, numverts, framenr ) ) + return; - if(clmd->clothObject == NULL) - return result; + if ( clmd->clothObject == NULL ) + return; cloth = clmd->clothObject; } - /* - deltaTime = 0; - while( deltaTime < 1.0) - { - step(cloth->m_fc, 0.1); - deltaTime+=0.1; - } - */ - clmd->clothObject->old_solver_type = clmd->sim_parms->solver_type; + + 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 ( clmd->clothObject != NULL ) { if(!cloth_read_cache(ob, clmd, framenr)) { + verts = cloth->verts; + // Force any pinned verts to their constrained location. - // has to be commented for verlet - for ( i = 0; i < clmd->clothObject->numverts; i++ ) + for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) { // Save the previous position. - VECCOPY ( cloth->xold[i], cloth->xconst[i] ); - VECCOPY ( cloth->current_xold[i], cloth->x[i] ); + VECCOPY ( verts->xold, verts->xconst ); + VECCOPY ( verts->txold, verts->x ); + // Get the current position. - VECCOPY ( cloth->xconst[i], mvert[i].co ); - Mat4MulVecfl ( ob->obmat, cloth->xconst[i] ); + VECCOPY ( verts->xconst, vertexCos[i] ); + Mat4MulVecfl ( ob->obmat, verts->xconst ); } - + tstart(); - - /* Call the solver. */ - - if (solvers [clmd->sim_parms->solver_type].solver) - solvers [clmd->sim_parms->solver_type].solver (ob, framenr, clmd, effectors); - + + // 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()); - + printf ( "Cloth simulation time: %f\n", ( float ) tval() ); + cloth_write_cache(ob, clmd, framenr); + + } + else // just retrieve the cached frame + { + cloth_read_cache(ob, clmd, framenr); } // Copy the result back to the object. - cloth_to_object (ob, result, clmd); - + cloth_to_object ( ob, clmd, vertexCos, numverts ); + // bvh_free(clmd->clothObject->tree); - // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms->epsilon); - } + // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon); + } } else if ( ( deltaTime <= 0.0f ) || ( deltaTime > 1.0f ) ) @@ -675,147 +679,85 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *d if ( clmd->clothObject != NULL ) { if(cloth_read_cache(ob, clmd, framenr)) - cloth_to_object (ob, result, clmd); + cloth_to_object ( ob, clmd, vertexCos, numverts ); } else { cloth_clear_cache(ob, clmd, 0); } } - - cloth = clmd->clothObject; - /* - if(cloth) - { - if (_texture_data == NULL) - _texture_data = (unsigned char*) malloc((30+2)*(30+2)*(30+2)*4); - - for (i=0; i<(30+2)*(30+2)*(30+2); i++) { - _texture_data[(i<<2)] = (unsigned char) (cloth->m_fc->T[i] * 255.0f); - _texture_data[(i<<2)+1] = (unsigned char) (cloth->m_fc->d[i] * 255.0f); - _texture_data[(i<<2)+2] = 0; - _texture_data[(i<<2)+3] = 255; - } - - // from ligth constructor - _light_dir[0] = -1.0f; - _light_dir[1] = 0.5f; - _light_dir[2] = 0.0f; - - gen_ray_templ(_ray_templ, _light_dir, 30 + 2); - - cast_light(_texture_data, _ray_templ, _light_dir, 30+2); - - glActiveTextureARB(GL_TEXTURE0_ARB); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 30+2, 30+2, 30+2, 0, GL_RGBA, GL_UNSIGNED_BYTE, _texture_data); - free(_texture_data); - } - */ - return result; + } /* frees all */ -void cloth_free_modifier (ClothModifierData *clmd) +void cloth_free_modifier ( ClothModifierData *clmd ) { Cloth *cloth = NULL; - - if(!clmd) + Object *ob = clmd->sim_parms.ob; + + if ( !clmd ) return; cloth = clmd->clothObject; - // free our frame cache - // cloth_clear_cache(ob, clmd, 0); + if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT ) ) + { + if ( cloth ) + { + // free our frame cache, TODO: but get to first position before + if(ob) + cloth_clear_cache ( ob, clmd, 0 ); + + // 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 ); - /* Calls the solver and collision frees first as they - * might depend on data in clmd->clothObject. */ + cloth->verts = NULL; + cloth->numverts = 0; - if (cloth) - { - f_free(cloth->m_fc); - - // 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) + // Free the springs. + if ( cloth->springs != NULL ) { - ClothSpring *spring = search->link; - - MEM_freeN ( spring ); - search = search->next; + 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; } - BLI_linklist_free(cloth->springs, NULL); - + cloth->springs = NULL; + cloth->numsprings = 0; + + // free BVH collision tree + if ( cloth->tree ) + bvh_free ( ( BVH * ) cloth->tree ); + + // we save our faces for collision objects + if ( cloth->mfaces ) + MEM_freeN ( cloth->mfaces ); + /* + if(clmd->clothObject->facemarks) + MEM_freeN(clmd->clothObject->facemarks); + */ + MEM_freeN ( cloth ); + clmd->clothObject = 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. @@ -823,44 +765,42 @@ void cloth_free_modifier (ClothModifierData *clmd) ******************************************************************************/ /** - * 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) +* 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, ClothModifierData *clmd, float ( *vertexCos ) [3], unsigned int numverts ) { + ClothVertex *verts = NULL; 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); + if ( clmd->clothObject ) + { + verts = clmd->clothObject->verts; - mvert = CDDM_get_verts(dm); - numverts = dm->getNumVerts(dm); + /* inverse matrix is not uptodate... */ + Mat4Invert ( ob->imat, ob->obmat ); - for (i = 0; i < numverts; i++) + for ( i = 0; i < numverts; i++, verts++ ) { - VECCOPY (mvert[i].co, cloth->x[i]); - Mat4MulVecfl (ob->imat, mvert[i].co); /* cloth is in global coords */ + VECCOPY ( vertexCos[i], verts->x ); + Mat4MulVecfl ( ob->imat, vertexCos[i] ); /* softbody 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) +* 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; + MDeformVert *dvert = NULL; Cloth *clothObj = NULL; - unsigned int numverts = 0; + unsigned int numverts = dm->getNumVerts ( dm ); float goalfac = 0; ClothVertex *verts = NULL; @@ -869,7 +809,7 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v if ( !dm ) return; - numverts = dm->getNumVerts(dm); + numverts = dm->getNumVerts ( dm ); /* vgroup is 1 based, decrement so we can match the right group. */ --vgroup; @@ -879,7 +819,7 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v for ( i = 0; i < numverts; i++, verts++ ) { // LATER ON, support also mass painting here - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) { dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); if ( dvert ) @@ -890,7 +830,7 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v { verts->goal = dvert->dw [j].weight; - goalfac= ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); + goalfac= ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal ); verts->goal = ( float ) pow ( verts->goal , 4.0f ); if ( dvert->dw [j].weight >=SOFTGOALSNAP ) @@ -907,194 +847,226 @@ static void cloth_apply_vgroup(ClothModifierData *clmd, DerivedMesh *dm, short v } } } - + // only meshes supported at the moment -static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, DerivedMesh *olddm, float framenr) +/* collision objects */ +static int collobj_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts ) { unsigned int i; - unsigned int numverts = dm->getNumVerts(dm); - MVert *mvert = CDDM_get_verts(dm); + MVert *mvert = NULL; + ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; - Cloth *cloth = NULL; - + /* If we have a clothObject, free it. */ - if (clmd->clothObject != NULL) - cloth_free_modifier (clmd); + 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 = MEM_callocN ( sizeof ( Cloth ), "cloth" ); + if ( clmd->clothObject ) { clmd->clothObject->old_solver_type = 255; - clmd->clothObject->edgehash = NULL; + // clmd->clothObject->old_collision_type = 255; } - else if (clmd->clothObject == NULL) + else if ( clmd->clothObject == NULL ) { - modifier_setError (&(clmd->modifier), "Out of memory on allocating clmd->clothObject."); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." ); return 0; } - - cloth = clmd->clothObject; - - cloth->m_fc = f_init(); - // open file - m_fc_open(clmd); + switch ( ob->type ) + { + case OB_MESH: + + // mesh input objects need DerivedMesh + if ( !dm ) + return 0; + + cloth_from_mesh ( ob, clmd, dm ); + + if ( clmd->clothObject != NULL ) + { + if ( !dm ) return 0; + if ( !dm->getNumVerts ( dm ) || !dm->getNumFaces ( dm ) ) return 0; + + mvert = dm->getVertArray ( dm ); + verts = clmd->clothObject->verts; + numverts = clmd->clothObject->numverts = dm->getNumVerts ( dm ); + + for ( i = 0; i < numverts; i++, verts++ ) + { + VECCOPY ( verts->x, mvert[i].co ); + Mat4MulVecfl ( ob->obmat, verts->x ); + verts->flags = 0; + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->txold, verts->x ); + VECCOPY ( verts->tx, verts->x ); + VecMulf ( verts->v, 0.0f ); + verts->impulse_count = 0; + VECCOPY ( verts->impulse, tnull ); + } + clmd->clothObject->tree = bvh_build ( clmd,clmd->coll_parms.epsilon ); + + } + + return 1; + default: return 0; // TODO - we do not support changing meshes + } +} - switch (ob->type) +/* +helper function to get proper spring length +when object is rescaled +*/ +float cloth_globallen ( float *v1,float *v2,Object *ob ) +{ + float p1[3],p2[3]; + VECCOPY ( p1,v1 ); + Mat4MulVecfl ( ob->obmat, p1 ); + VECCOPY ( p2,v2 ); + Mat4MulVecfl ( ob->obmat, p2 ); + return VecLenf ( p1,p2 ); +} + +// only meshes supported at the moment +static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float ( *vertexCos ) [3], unsigned int numverts, float framenr ) +{ + unsigned int i = 0; + // dm->getNumVerts(dm); + MVert *mvert = NULL; // CDDM_get_verts(dm); + ClothVertex *verts = NULL; + 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->old_collision_type = 255; + } + else if ( !clmd->clothObject ) + { + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject." ); + return 0; + } + + clmd->sim_parms.ob = ob; + + switch ( ob->type ) { case OB_MESH: - + // mesh input objects need DerivedMesh if ( !dm ) return 0; - cloth_from_mesh (ob, clmd, dm, framenr); + cloth_from_mesh ( ob, clmd, dm ); if ( clmd->clothObject != NULL ) { /* create springs */ clmd->clothObject->springs = NULL; clmd->clothObject->numsprings = -1; - + + mvert = CDDM_get_verts ( dm ); + verts = clmd->clothObject->verts; + /* set initial values */ - for (i = 0; i < numverts; ++i) + for ( i = 0; i < numverts; i++, verts++ ) { - 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; + VECCOPY ( verts->x, mvert[i].co ); + Mat4MulVecfl ( ob->obmat, verts->x ); + + verts->mass = clmd->sim_parms.mass; + + if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + verts->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 ); + verts->goal= 0.0f; + + verts->flags = 0; + VECCOPY ( verts->xold, verts->x ); + VECCOPY ( verts->xconst, verts->x ); + VECCOPY ( verts->txold, verts->x ); + VecMulf ( verts->v, 0.0f ); + + verts->impulse_count = 0; + VECCOPY ( verts->impulse, tnull ); } - if (!cloth_build_springs (clmd, dm) ) + if ( !cloth_build_springs ( clmd->clothObject, dm ) ) { - modifier_setError (&(clmd->modifier), "Can't build springs."); + 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 + } + + // apply / set vertex groups + if ( clmd->sim_parms.vgroup_mass > 0 ) + cloth_apply_vgroup ( clmd, dm, 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 ( clmd, clmd->coll_parms.epsilon ); + cloth_write_cache(ob, clmd, framenr-1); } + + return 1; + case OB_LATTICE: + printf ( "Not supported: OB_LATTICE\n" ); + // lattice_to_softbody(ob); return 1; - default: return 0; // TODO - we do not support changing meshes + case OB_CURVE: + case OB_SURF: + printf ( "Not supported: OB_SURF| OB_CURVE\n" ); + 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) +static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) { - unsigned int numverts = dm->getNumVerts(dm); - unsigned int numfaces = dm->getNumFaces(dm); - MFace *mface = CDDM_get_faces(dm); + unsigned int numverts = dm->getNumVerts ( dm ); + unsigned int numfaces = dm->getNumFaces ( dm ); + MFace *mface = dm->getFaceArray ( dm ); + unsigned int i = 0; /* 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 ) + 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->xconst." ); + modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->verts." ); return; } // save face information clmd->clothObject->numfaces = numfaces; - clmd->clothObject->mfaces = MEM_callocN (sizeof (MFace) * clmd->clothObject->numfaces, "clothMFaces"); - if (clmd->clothObject->mfaces == NULL) + 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."); + 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); + for ( i = 0; i < numfaces; i++ ) + memcpy ( &clmd->clothObject->mfaces[i], &mface[i], sizeof ( MFace ) ); /* Free the springs since they can't be correct if the vertices * changed. */ - if (clmd->clothObject->springs != NULL) - MEM_freeN (clmd->clothObject->springs); + if ( clmd->clothObject->springs != NULL ) + MEM_freeN ( clmd->clothObject->springs ); } @@ -1103,7 +1075,6 @@ static void cloth_from_mesh (Object *ob, ClothModifierData *clmd, DerivedMesh *d ***************************************************************************************/ // be carefull: implicit solver has to be resettet when using this one! -// --> only for implicit handling of this spring! int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type) { Cloth *cloth = clmd->clothObject; @@ -1130,12 +1101,11 @@ int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned in return 0; } -int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) +int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm ) { - Cloth *cloth = clmd->clothObject; ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0; - unsigned int i = 0, j = 0, akku_count; + unsigned int i = 0; unsigned int numverts = dm->getNumVerts ( dm ); unsigned int numedges = dm->getNumEdges ( dm ); unsigned int numfaces = dm->getNumFaces ( dm ); @@ -1145,9 +1115,9 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) LinkNode **edgelist = NULL; EdgeHash *edgehash = NULL; LinkNode *search = NULL, *search2 = NULL; - float temp[3], akku, min, max; - LinkNode *node = NULL, *node2 = NULL; - + float temp[3]; + ClothVertex *verts = NULL; + // error handling if ( numedges==0 ) return 0; @@ -1162,6 +1132,8 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) if ( cloth->springs ) MEM_freeN ( cloth->springs ); + + verts = cloth->verts; // create spring network hash edgehash = BLI_edgehash_new(); @@ -1175,54 +1147,16 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) { spring->ij = medge[i].v1; spring->kl = medge[i].v2; - VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] ); + VECSUB ( temp, verts[spring->kl].x, verts[spring->ij].x ); 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++ ) - { - akku_count = 0; - akku = 0.0; - cloth->verts[i].collball=0; - min = 1e22f; - max = -1e22f; - - search = cloth->springs; - for ( j = 0; j < struct_springs; j++ ) - { - if ( !search ) - break; - tspring = search->link; - - if((tspring->ij == i) || (tspring->kl == i)) - { - akku += spring->restlen; - akku_count++; - min = MIN2(spring->restlen,min); - max = MAX2(spring->restlen,max); - } + BLI_linklist_append ( &cloth->springs, spring ); } - - if (akku_count > 0) { - cloth->verts[i].collball = akku/(float)akku_count*clmd->coll_parms->selfepsilon; - } - else cloth->verts[i].collball=0; } - + // shear springs for ( i = 0; i < numfaces; i++ ) { @@ -1230,7 +1164,7 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring->ij = mface[i].v1; spring->kl = mface[i].v3; - VECSUB ( temp, cloth->x[spring->kl], cloth->x[spring->ij] ); + VECSUB ( temp, verts[spring->kl].x, verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_SHEAR; @@ -1238,8 +1172,7 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) BLI_linklist_append ( &edgelist[spring->kl], spring ); shear_springs++; - node2 = BLI_linklist_append_fast ( &node->next, spring ); - node = node2; + BLI_linklist_append ( &cloth->springs, spring ); if ( mface[i].v4 ) { @@ -1247,19 +1180,18 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) 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; + VECSUB ( temp, verts[spring->kl].x, verts[spring->ij].x ); + 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++; + 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; + BLI_linklist_append ( &cloth->springs, spring ); } } - + // bending springs search2 = cloth->springs; for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) @@ -1277,38 +1209,36 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) // 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 ) ) + && !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] ); + VECSUB ( temp, verts[index2].x, verts[tspring2->ij].x ); 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; + BLI_linklist_append ( &cloth->springs, spring ); } search = search->next; } search2 = search2->next; } - - cloth->numspringssave = cloth->numsprings = struct_springs + shear_springs + bend_springs; - cloth->numothersprings = struct_springs + shear_springs; - + + cloth->numsprings = struct_springs + shear_springs + bend_springs; + for ( i = 0; i < numverts; i++ ) { BLI_linklist_free ( edgelist[i],NULL ); } if ( edgelist ) MEM_freeN ( edgelist ); - - cloth->edgehash = edgehash; + + BLI_edgehash_free ( edgehash, NULL ); return 1; @@ -1317,344 +1247,3 @@ int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) * SPRING NETWORK BUILDING IMPLEMENTATION END ***************************************************************************************/ -#define F_ITER 20 -#define m_diffusion 0.00001f -#define m_viscosity 0.000f -#define m_buoyancy 1.5f -#define m_cooling 1.0f -#define m_vc_eps 4.0f - -#define GRID_SIZE 30 -#define SIZE ((GRID_SIZE+2)*(GRID_SIZE+2)*(GRID_SIZE+2)) -#define _I(x,y,z) (((z)<<10)+((y)<<5)+x) - -#define SWAPFPTR(x,y) {float *t=x;x=y;y=t;} - -float buffers[10][SIZE]; -float sd[SIZE], su[SIZE], sv[SIZE], sw[SIZE], sT[SIZE]; - - -// nothing to do in this mode -// add code for 2nd mode -void set_bnd(int b, float* x, int N) -{ -} - -void lin_solve(int b, float *x, float *x0, float a, float c, int N) -{ - float cRecip = 1.0 / c; - int i, j, k, l; - for (l=0; l<F_ITER; l++) - { - for (k=1; k<=N; k++) - { - for (j=1; j<=N; j++) - { - for (i=1; i<=N; i++) - { - x[_I(i,j,k)] = (x0[_I(i,j,k)] + a*( - x[_I(i-1,j,k)]+x[_I(i+1,j,k)]+ - x[_I(i,j-1,k)]+x[_I(i,j+1,k)]+ - x[_I(i,j,k-1)]+x[_I(i,j,k+1)]))*cRecip; - } - } - } - set_bnd(b, x, N); - } -} - -void add_source(float* src, float *dst, float dt, int N) -{ - int i, size=(N+2)*(N+2)*(N+2); - - for (i=0; i<size; i++) - dst[i] += src[i]*dt; -} - -void add_buoyancy(float *v, float* T, float dt, float buoyancy, int N) -{ - int i, size=(N+2)*(N+2)*(N+2); - - for (i=0; i<size; i++) - v[i] += -T[i]*buoyancy*dt; -} - -void diffuse(int b, float* x0, float* x, float diff, float dt, int N) -{ - float a=dt*diff*N*N*N; - lin_solve(b, x, x0, a, 1 + 6 * a, N); -} - - -void advect(int b, float* x0, float* x, float* uu, float* vv, float* ww, float dt, int N) -{ - int i, j, k, i0, j0, k0, i1, j1, k1; - float sx0, sx1, sy0, sy1, sz0, sz1, v0, v1; - float xx, yy, zz, dt0; - dt0 = dt*N; - for (k=1; k<=N; k++) - { - for (j=1; j<=N; j++) - { - for (i=1; i<=N; i++) - { - xx = i-dt0*uu[_I(i,j,k)]; - yy = j-dt0*vv[_I(i,j,k)]; - zz = k-dt0*ww[_I(i,j,k)]; - if (xx<0.5) xx=0.5f; if (xx>N+0.5) xx=N+0.5f; i0=(int)xx; i1=i0+1; - if (yy<0.5) yy=0.5f; if (yy>N+0.5) yy=N+0.5f; j0=(int)yy; j1=j0+1; - if (zz<0.5) zz=0.5f; if (zz>N+0.5) zz=N+0.5f; k0=(int)zz; k1=k0+1; - sx1 = xx-i0; sx0 = 1-sx1; - sy1 = yy-j0; sy0 = 1-sy1; - sz1 = zz-k0; sz0 = 1-sz1; - v0 = sx0*(sy0*x0[_I(i0,j0,k0)]+sy1*x0[_I(i0,j1,k0)])+sx1*(sy0*x0[_I(i1,j0,k0)]+sy1*x0[_I(i1,j1,k0)]); - v1 = sx0*(sy0*x0[_I(i0,j0,k1)]+sy1*x0[_I(i0,j1,k1)])+sx1*(sy0*x0[_I(i1,j0,k1)]+sy1*x0[_I(i1,j1,k1)]); - x[_I(i,j,k)] = sz0*v0 + sz1*v1; - } - } - } - set_bnd(b,x, N); -} - -void advect_cool(int b, float* x0, float* x, float* y0, float* y, float* uu, float* vv, float* ww, float dt, float cooling, int N) -{ - int i, j, k, i0, j0, k0, i1, j1, k1; - float sx0, sx1, sy0, sy1, sz0, sz1, v0, v1; - float xx, yy, zz, dt0, c0; - dt0 = dt*N; - c0 = 1.0f - cooling*dt; - for (k=1; k<=N; k++) - { - for (j=1; j<=N; j++) - { - for (i=1; i<=N; i++) - { - xx = i-dt0*uu[_I(i,j,k)]; - yy = j-dt0*vv[_I(i,j,k)]; - zz = k-dt0*ww[_I(i,j,k)]; - if (xx<0.5) xx=0.5f; if (xx>N+0.5) xx=N+0.5f; i0=(int)xx; i1=i0+1; - if (yy<0.5) yy=0.5f; if (yy>N+0.5) yy=N+0.5f; j0=(int)yy; j1=j0+1; - if (zz<0.5) zz=0.5f; if (zz>N+0.5) zz=N+0.5f; k0=(int)zz; k1=k0+1; - sx1 = xx-i0; sx0 = 1-sx1; - sy1 = yy-j0; sy0 = 1-sy1; - sz1 = zz-k0; sz0 = 1-sz1; - v0 = sx0*(sy0*x0[_I(i0,j0,k0)]+sy1*x0[_I(i0,j1,k0)])+sx1*(sy0*x0[_I(i1,j0,k0)]+sy1*x0[_I(i1,j1,k0)]); - v1 = sx0*(sy0*x0[_I(i0,j0,k1)]+sy1*x0[_I(i0,j1,k1)])+sx1*(sy0*x0[_I(i1,j0,k1)]+sy1*x0[_I(i1,j1,k1)]); - x[_I(i,j,k)] = sz0*v0 + sz1*v1; - v0 = sx0*(sy0*y0[_I(i0,j0,k0)]+sy1*y0[_I(i0,j1,k0)])+sx1*(sy0*y0[_I(i1,j0,k0)]+sy1*y0[_I(i1,j1,k0)]); - v1 = sx0*(sy0*y0[_I(i0,j0,k1)]+sy1*y0[_I(i0,j1,k1)])+sx1*(sy0*y0[_I(i1,j0,k1)]+sy1*y0[_I(i1,j1,k1)]); - y[_I(i,j,k)] = (sz0*v0 + sz1*v1)*c0; - } - } - } - set_bnd(b,x, N); - set_bnd(b,y, N); -} - -void fproject(float* u, float* u0, float* v, float* v0, float* w, float* w0, int N) -{ - float* p = u0; float* div = v0; // temporary buffers, use old velocity buffers - int i, j, k; - float h; - h = 1.0f/N; - for (k=1; k<=N; k++) { - for (j=1; j<=N; j++) { - for (i=1; i<=N; i++) { - div[_I(i,j,k)] = -h*( - u[_I(i+1,j,k)]-u[_I(i-1,j,k)]+ - v[_I(i,j+1,k)]-v[_I(i,j-1,k)]+ - w[_I(i,j,k+1)]-w[_I(i,j,k-1)])*0.5; - p[_I(i,j,k)] = 0; - } - } - } - set_bnd(0, div, N); - set_bnd(0, p, N); - lin_solve(0, p, div, 1, 6, N); - - for (k=1; k<=N; k++) { - for (j=1; j<=N; j++) { - for (i=1; i<=N; i++) { - u[_I(i,j,k)] -= (p[_I(i+1,j,k)]-p[_I(i-1,j,k)])*0.5*N; - v[_I(i,j,k)] -= (p[_I(i,j+1,k)]-p[_I(i,j-1,k)])*0.5*N; - w[_I(i,j,k)] -= (p[_I(i,j,k+1)]-p[_I(i,j,k-1)])*0.5*N; - } - } - } - set_bnd(1, u, N); - set_bnd(2, v, N); - set_bnd(3, w, N); -} - -void vorticity_confinement(float *T0, float* u, float* u0, float* v, float* v0, float* w, float* w0, float dt, float vc_eps, int N) -{ - int i,j,k,ijk; - float *curlx = u0, *curly = v0, *curlz=w0, *curl=T0; // temp buffers - float dt0 = dt * vc_eps; - float x,y,z; - - - for (k=1; k<N; k++) { - for (j=1; j<N; j++) { - for (i=1; i<N; i++) { - ijk = _I(i,j,k); - // curlx = dw/dy - dv/dz - x = curlx[ijk] = (w[_I(i,j+1,k)] - w[_I(i,j-1,k)]) * 0.5f - - (v[_I(i,j,k+1)] - v[_I(i,j,k-1)]) * 0.5f; - - // curly = du/dz - dw/dx - y = curly[ijk] = (u[_I(i,j,k+1)] - u[_I(i,j,k-1)]) * 0.5f - - (w[_I(i+1,j,k)] - w[_I(i-1,j,k)]) * 0.5f; - - // curlz = dv/dx - du/dy - z = curlz[ijk] = (v[_I(i+1,j,k)] - v[_I(i-1,j,k)]) * 0.5f - - (u[_I(i,j+1,k)] - u[_I(i,j-1,k)]) * 0.5f; - - // curl = |curl| - curl[ijk] = sqrtf(x*x+y*y+z*z); - } - } - } - - for (k=1; k<N; k++) { - for (j=1; j<N; j++) { - for (i=1; i<N; i++) { - float Nx = (curl[_I(i+1,j,k)] - curl[_I(i-1,j,k)]) * 0.5f; - float Ny = (curl[_I(i,j+1,k)] - curl[_I(i,j-1,k)]) * 0.5f; - float Nz = (curl[_I(i,j,k+1)] - curl[_I(i,j,k-1)]) * 0.5f; - float len1 = 1.0f/(sqrtf(Nx*Nx+Ny*Ny+Nz*Nz)+0.0000001f); - ijk = _I(i,j,k); - Nx *= len1; - Ny *= len1; - Nz *= len1; - u[ijk] += (Ny*curlz[ijk] - Nz*curly[ijk]) * dt0; - v[ijk] += (Nz*curlx[ijk] - Nx*curlz[ijk]) * dt0; - w[ijk] += (Nx*curly[ijk] - Ny*curlx[ijk]) * dt0; - } - } - } -} - - - -#define DIFFUSE -#define ADVECT - -void vel_step(float *su, float *sv, float *sw, float* u, float* u0, float* v, float* v0, float* w, float* w0, float *T, float *T0, float dt, int N) -{ - add_source(su, u, dt, N); - add_source(sv, v, dt, N); - add_source(sw, w, dt, N); - - // external force - add_buoyancy(v, T, dt, m_buoyancy, N); // better is using gravity normal vector instead of v - - vorticity_confinement(T0, u, u0, v, v0, w, w0, dt, m_vc_eps, N); - -#ifdef DIFFUSE - SWAPFPTR(u0, u); SWAPFPTR(v0, v); SWAPFPTR(w0, w); - diffuse(1, u0, u, m_viscosity, dt, N); - diffuse(2, v0, v, m_viscosity, dt, N); - diffuse(3, w0, w, m_viscosity, dt, N); - fproject(u, u0, v, v0, w, w0, N); -#endif -#ifdef ADVECT - SWAPFPTR(u0, u); SWAPFPTR(v0, v); SWAPFPTR(w0, w); - advect(1, u0, u, u0, v0, w0, dt, N); - advect(2, v0, v, u0, v0, w0, dt, N); - advect(3, w0, w, u0, v0, w0, dt, N); - fproject(u, u0, v, v0, w, w0, N); -#endif -} - -void dens_step(float *sd, float *d, float *d0, float *u, float *v, float *w, float dt, int N) -{ - add_source(sd, d, dt, N); -#ifdef DIFFUSE - SWAPFPTR(d0, d); - diffuse(0, d0, d, m_diffusion, dt, N); -#endif -#ifdef ADVECT - SWAPFPTR(d0, d); - advect(0, d0, d, u, v, w, dt, N); -#endif -} - -void dens_temp_step(float *sd, float *sT, float *T, float *T0, float *d, float *d0, float *u, float *v, float *w, float dt, int N) -{ - add_source(sd, d, dt, N); - add_source(sT, T, dt, N); - SWAPFPTR(d0, d); - diffuse(0, d0, d, m_diffusion, dt, N); - SWAPFPTR(d0, d); - SWAPFPTR(T0, T); - advect_cool(0, d0, d, T0, T, u, v, w, dt, m_cooling, N); -} - -void step(fc *m_fc, float dt) -{ - vel_step(su, sv, sw, m_fc->u, m_fc->u0, m_fc->v, m_fc->v0, m_fc->w, m_fc->w0, m_fc->T, m_fc->T0, dt, GRID_SIZE); - dens_temp_step(sd, sT, m_fc->T, m_fc->T0, m_fc->d, m_fc->d0, m_fc->u, m_fc->v, m_fc->w, dt, GRID_SIZE); -} - - - -void clear_buffer(float* x) -{ - int i; - for (i=0; i<SIZE; i++) { - x[i] = 0.0f; - } -} - -void clear_sources(float *sd, float *su, float *sv) -{ - int i; - for (i=0; i<SIZE; i++) { - sd[i] = su[i] = sv[i] = 0.0f; - } -} - -fc *f_init(void) -{ - int i; - int size; - - fc *m_fc = MEM_callocN(sizeof(fc), "f_c"); - for (i=0; i<10; i++) - clear_buffer(buffers[i]); - - i=0; - m_fc->d=buffers[i++]; m_fc->d0=buffers[i++]; - m_fc->T=buffers[i++]; m_fc->T0=buffers[i++]; - m_fc->u=buffers[i++]; m_fc->u0=buffers[i++]; - m_fc->v=buffers[i++]; m_fc->v0=buffers[i++]; - m_fc->w=buffers[i++]; m_fc->w0=buffers[i++]; - - clear_sources(sd, su, sv); - - size=(GRID_SIZE+2)*(GRID_SIZE+2)*(GRID_SIZE+2); - for (i=0; i<size; i++) - m_fc->v[i] = -0.5f; - - m_fc->_texture_data = (unsigned char*) MEM_callocN((30+2)*(30+2)*(30+2)*4, "fc_texture_data"); - - m_fc->_fp = 0; - - return m_fc; -} - -void f_free(fc *m_fc) -{ - if(m_fc) - { - if(m_fc->_texture_data) - MEM_freeN(m_fc->_texture_data); - - if(m_fc->_fp) - fclose(m_fc->_fp); - - MEM_freeN(m_fc); - } -} - diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 4bc1efc1e70..4a03f579fe8 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -49,7 +49,6 @@ #include "BLI_arithb.h" #include "BLI_edgehash.h" #include "BLI_linklist.h" -#include "BKE_collisions.h" #include "BKE_curve.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" @@ -71,20 +70,6 @@ #include "Bullet-C-Api.h" -// step is limited from 0 (frame start position) to 1 (frame end position) -void collision_move_object(CollisionModifierData *collmd, float step, float prevstep) -{ - float tv[3] = {0,0,0}; - unsigned int i = 0; - - for ( i = 0; i < collmd->numverts; i++ ) - { - VECSUB(tv, collmd->xnew[i].co, collmd->x[i].co); - VECADDS(collmd->current_x[i].co, collmd->x[i].co, tv, prevstep); - VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step); - VECSUB(collmd->current_v[i].co, collmd->current_xnew[i].co, collmd->current_x[i].co); - } -} /** @@ -232,7 +217,7 @@ int gsl_poly_solve_quadratic (float a, float b, float c, float *x0, float *x1) * page 4, left column */ -int collisions_get_collision_time(float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3]) +int cloth_get_collision_time(float a[3], float b[3], float c[3], float d[3], float e[3], float f[3], float solution[3]) { int num_sols = 0; @@ -333,7 +318,7 @@ int collisions_get_collision_time(float a[3], float b[3], float c[3], float d[3] } // w3 is not perfect -void collisions_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) +void cloth_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3) { double tempV1[3], tempV2[3], tempV4[3]; double a,b,c,d,e,f; @@ -376,3 +361,884 @@ DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], floa VECADDMUL(to, v3, w3); } +// unused in the moment, has some bug in +DO_INLINE void calculateFrictionImpulse(float to[3], float vrel[3], float normal[3], double normalVelocity, + double frictionConstant, double delta_V_n) +{ + float vrel_t_pre[3]; + float vrel_t[3]; + VECSUBS(vrel_t_pre, vrel, normal, normalVelocity); + VECCOPY(to, vrel_t_pre); + VecMulf(to, MAX2(1.0f - frictionConstant * delta_V_n / INPR(vrel_t_pre,vrel_t_pre), 0.0f)); +} + +int cloth_collision_response_static(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + unsigned int i = 0; + int result = 0; + LinkNode *search = NULL; + CollPair *collpair = NULL; + Cloth *cloth1, *cloth2; + float w1, w2, w3, u1, u2, u3; + float v1[3], v2[3], relativeVelocity[3]; + float magrelVel; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + search = clmd->coll_parms.collision_list; + + while(search) + { + collpair = search->link; + + // compute barycentric coordinates for both collision points + cloth_compute_barycentric(collpair->pa, + cloth1->verts[collpair->ap1].txold, + cloth1->verts[collpair->ap2].txold, + cloth1->verts[collpair->ap3].txold, + &w1, &w2, &w3); + + cloth_compute_barycentric(collpair->pb, + cloth2->verts[collpair->bp1].txold, + cloth2->verts[collpair->bp2].txold, + cloth2->verts[collpair->bp3].txold, + &u1, &u2, &u3); + + // Calculate relative "velocity". + interpolateOnTriangle(v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3); + + interpolateOnTriangle(v2, cloth2->verts[collpair->bp1].tv, cloth2->verts[collpair->bp2].tv, cloth2->verts[collpair->bp3].tv, u1, u2, u3); + + VECSUB(relativeVelocity, v1, v2); + + // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). + magrelVel = INPR(relativeVelocity, collpair->normal); + + // printf("magrelVel: %f\n", magrelVel); + + // Calculate masses of points. + + // If v_n_mag < 0 the edges are approaching each other. + if(magrelVel < -ALMOST_ZERO) + { + // Calculate Impulse magnitude to stop all motion in normal direction. + // const double I_mag = v_n_mag / (1/m1 + 1/m2); + float magnitude_i = magrelVel / 2.0f; // TODO implement masses + float tangential[3], magtangent, magnormal, collvel[3]; + float vrel_t_pre[3]; + float vrel_t[3]; + double impulse; + float epsilon = clmd->coll_parms.epsilon; + float overlap = (epsilon + ALMOST_ZERO-collpair->distance); + + // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); + + // magtangent = INPR(tangential, tangential); + + // Apply friction impulse. + if (magtangent < -ALMOST_ZERO) + { + + // printf("friction applied: %f\n", magtangent); + // TODO check original code + /* + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v2].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v3].tv,tangential); + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v4].tv,tangential); + */ + } + + + impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + // printf("impulse: %f\n", impulse); + + VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); + cloth1->verts[collpair->ap1].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); + cloth1->verts[collpair->ap2].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); + cloth1->verts[collpair->ap3].impulse_count++; + + result = 1; + + /* + if (overlap > ALMOST_ZERO) { + double I_mag = overlap * 0.1; + + impulse = -I_mag / ( 1.0 + w1*w1 + w2*w2 + w3*w3); + + VECADDMUL(cloth1->verts[collpair->ap1].impulse, collpair->normal, w1 * impulse); + cloth1->verts[collpair->ap1].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap2].impulse, collpair->normal, w2 * impulse); + cloth1->verts[collpair->ap2].impulse_count++; + + VECADDMUL(cloth1->verts[collpair->ap3].impulse, collpair->normal, w3 * impulse); + cloth1->verts[collpair->ap3].impulse_count++; + } + */ + + // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case + + // Apply the impulse and increase impulse counters. + + /* + // calculateFrictionImpulse(tangential, collvel, collpair->normal, magtangent, clmd->coll_parms.friction*0.01, magtangent); + VECSUBS(vrel_t_pre, collvel, collpair->normal, magnormal); + // VecMulf(vrel_t_pre, clmd->coll_parms.friction*0.01f/INPR(vrel_t_pre,vrel_t_pre)); + magtangent = Normalize(vrel_t_pre); + VecMulf(vrel_t_pre, MIN2(clmd->coll_parms.friction*0.01f*magnormal,magtangent)); + + VECSUB(cloth1->verts[face1->v1].tv, cloth1->verts[face1->v1].tv,vrel_t_pre); + */ + + + + } + + search = search->next; + } + + + return result; +} + +int cloth_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + +} + + +int cloth_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) +{ + +} + +void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + CollPair *collpair = NULL; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0; + + for(i = 0; i < 4; i++) + { + collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + // check all possible pairs of triangles + if(i == 0) + { + collpair->ap1 = face1->v1; + collpair->ap2 = face1->v2; + collpair->ap3 = face1->v3; + + collpair->bp1 = face2->v1; + collpair->bp2 = face2->v2; + collpair->bp3 = face2->v3; + + } + + if(i == 1) + { + if(face1->v4) + { + collpair->ap1 = face1->v3; + collpair->ap2 = face1->v4; + collpair->ap3 = face1->v1; + + collpair->bp1 = face2->v1; + collpair->bp2 = face2->v2; + collpair->bp3 = face2->v3; + } + else + i++; + } + + if(i == 2) + { + if(face2->v4) + { + collpair->ap1 = face1->v1; + collpair->ap2 = face1->v2; + collpair->ap3 = face1->v3; + + collpair->bp1 = face2->v3; + collpair->bp2 = face2->v4; + collpair->bp3 = face2->v1; + } + else + i+=2; + } + + if(i == 3) + { + if((face1->v4)&&(face2->v4)) + { + collpair->ap1 = face1->v3; + collpair->ap2 = face1->v4; + collpair->ap3 = face1->v1; + + collpair->bp1 = face2->v3; + collpair->bp2 = face2->v4; + collpair->bp3 = face2->v1; + } + else + i++; + } + + // calc SIPcode (?) + + if(i < 4) + { + // calc distance + normal + distance = plNearestPoints( + verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector); + + if (distance <= (epsilon + ALMOST_ZERO)) + { + // printf("dist: %f\n", (float)distance); + + // collpair->face1 = tree1->tri_index; + // collpair->face2 = tree2->tri_index; + + VECCOPY(collpair->normal, collpair->vector); + Normalize(collpair->normal); + + collpair->distance = distance; + BLI_linklist_append(&clmd->coll_parms.collision_list, collpair); + } + else + { + MEM_freeN(collpair); + } + } + else + { + MEM_freeN(collpair); + } + } +} + +int cloth_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) +{ + Cloth *cloth1, *cloth2; + ClothVertex *verts1, *verts2; + float temp[3]; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold); + if(ABS(INPR(temp, temp)) < ALMOST_ZERO) + return 1; + + return 0; +} + +void cloth_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + EdgeCollPair edgecollpair; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0, j = 0, k = 0; + int numsolutions = 0; + float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; + + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + for( i = 0; i < 5; i++) + { + if(i == 0) + { + edgecollpair.p11 = face1->v1; + edgecollpair.p12 = face1->v2; + } + else if(i == 1) + { + edgecollpair.p11 = face1->v2; + edgecollpair.p12 = face1->v3; + } + else if(i == 2) + { + if(face1->v4) + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v4; + } + else + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v1; + i+=5; // get out of here after this edge pair is handled + } + } + else if(i == 3) + { + if(face1->v4) + { + edgecollpair.p11 = face1->v4; + edgecollpair.p12 = face1->v1; + } + else + continue; + } + else + { + edgecollpair.p11 = face1->v3; + edgecollpair.p12 = face1->v1; + } + + + for( j = 0; j < 5; j++) + { + if(j == 0) + { + edgecollpair.p21 = face2->v1; + edgecollpair.p22 = face2->v2; + } + else if(j == 1) + { + edgecollpair.p21 = face2->v2; + edgecollpair.p22 = face2->v3; + } + else if(j == 2) + { + if(face2->v4) + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v4; + } + else + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v1; + } + } + else if(j == 3) + { + if(face2->v4) + { + edgecollpair.p21 = face2->v4; + edgecollpair.p22 = face2->v1; + } + else + continue; + } + else + { + edgecollpair.p21 = face2->v3; + edgecollpair.p22 = face2->v1; + } + + + if(!cloth_are_edges_adjacent(clmd, coll_clmd, &edgecollpair)) + { + VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold); + VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v); + VECSUB(c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold); + VECSUB(d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v); + VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold); + VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v); + + numsolutions = cloth_get_collision_time(a, b, c, d, e, f, solution); + + for (k = 0; k < numsolutions; k++) + { + if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) + { + float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into (edge) collision list + + // printf("Moving edge found!\n"); + } + } + } + } + } +} + +void cloth_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + CollPair collpair; + Cloth *cloth1=NULL, *cloth2=NULL; + MFace *face1=NULL, *face2=NULL; + ClothVertex *verts1=NULL, *verts2=NULL; + double distance = 0; + float epsilon = clmd->coll_parms.epsilon; + unsigned int i = 0, j = 0, k = 0; + int numsolutions = 0; + float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; + + for(i = 0; i < 2; i++) + { + cloth1 = clmd->clothObject; + cloth2 = coll_clmd->clothObject; + + verts1 = cloth1->verts; + verts2 = cloth2->verts; + + face1 = &(cloth1->mfaces[tree1->tri_index]); + face2 = &(cloth2->mfaces[tree2->tri_index]); + + // check all possible pairs of triangles + if(i == 0) + { + collpair.ap1 = face1->v1; + collpair.ap2 = face1->v2; + collpair.ap3 = face1->v3; + + collpair.pointsb[0] = face2->v1; + collpair.pointsb[1] = face2->v2; + collpair.pointsb[2] = face2->v3; + collpair.pointsb[3] = face2->v4; + } + + if(i == 1) + { + if(face1->v4) + { + collpair.ap1 = face1->v3; + collpair.ap2 = face1->v4; + collpair.ap3 = face1->v1; + + collpair.pointsb[0] = face2->v1; + collpair.pointsb[1] = face2->v2; + collpair.pointsb[2] = face2->v3; + collpair.pointsb[3] = face2->v4; + } + else + i++; + } + + // calc SIPcode (?) + + if(i < 2) + { + VECSUB(a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold); + VECSUB(b, verts1[collpair.ap2].v, verts1[collpair.ap1].v); + VECSUB(c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold); + VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v); + + for(j = 0; j < 4; j++) + { + if((j==3) && !(face2->v4)) + break; + + VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold); + VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v); + + numsolutions = cloth_get_collision_time(a, b, c, d, e, f, solution); + + for (k = 0; k < numsolutions; k++) + { + if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) + { + float out_collisionTime = solution[k]; + + // TODO: check for collisions + + // TODO: put into (point-face) collision list + + // printf("Moving found!\n"); + + } + } + + // TODO: check borders for collisions + } + + } + } +} + +void cloth_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, Tree *tree1, Tree *tree2) +{ + // TODO: check for adjacent + cloth_collision_moving_edges(clmd, coll_clmd, tree1, tree2); + + cloth_collision_moving_tris(clmd, coll_clmd, tree1, tree2); + cloth_collision_moving_tris(coll_clmd, clmd, tree2, tree1); +} + +// move collision objects forward in time and update static bounding boxes +void cloth_update_collision_objects(float step) +{ + Base *base=NULL; + ClothModifierData *coll_clmd=NULL; + Object *coll_ob=NULL; + unsigned int i=0; + + // search all objects for collision object + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + Cloth *coll_cloth = coll_clmd->clothObject; + BVH *coll_bvh = coll_clmd->clothObject->tree; + unsigned int coll_numverts = coll_cloth->numverts; + + // update position of collision object + for(i = 0; i < coll_numverts; i++) + { + VECCOPY(coll_cloth->verts[i].txold, coll_cloth->verts[i].tx); + + VECADDS(coll_cloth->verts[i].tx, coll_cloth->verts[i].xold, coll_cloth->verts[i].v, step); + + // no dt here because of float rounding errors + VECSUB(coll_cloth->verts[i].tv, coll_cloth->verts[i].tx, coll_cloth->verts[i].txold); + } + + // update BVH of collision object + bvh_update(coll_clmd, coll_bvh, 0); // 0 means STATIC, 1 means MOVING + } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } +} + +// CLOTH_MAX_THRESHOLD defines how much collision rounds/loops should be taken +#define CLOTH_MAX_THRESHOLD 10 + +// cloth - object collisions +int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float dt) +{ + Base *base=NULL; + ClothModifierData *coll_clmd=NULL; + Cloth *cloth=NULL; + Object *coll_ob=NULL; + BVH *cloth_bvh=NULL; + unsigned int i=0, j = 0, numfaces = 0, numverts = 0; + unsigned int result = 0, ic = 0, rounds = 0; // result counts applied collisions; ic is for debug output; + ClothVertex *verts = NULL; + float tnull[3] = {0,0,0}; + int ret = 0; + + if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree)) + { + return 0; + } + cloth = clmd->clothObject; + verts = cloth->verts; + cloth_bvh = (BVH *) cloth->tree; + numfaces = clmd->clothObject->numfaces; + numverts = clmd->clothObject->numverts; + + //////////////////////////////////////////////////////////// + // static collisions + //////////////////////////////////////////////////////////// + + // update cloth bvh + bvh_update(clmd, cloth_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function) + + // update collision objects + cloth_update_collision_objects(step); + + do + { + result = 0; + ic = 0; + clmd->coll_parms.collision_list = NULL; + + // check all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_static); + } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence + { + result = 0; + + // handle all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject) + result += cloth_collision_response_static(clmd, coll_clmd); + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + + // free collision list + if(clmd->coll_parms.collision_list) + { + LinkNode *search = clmd->coll_parms.collision_list; + while(search) + { + CollPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(clmd->coll_parms.collision_list,NULL); + + clmd->coll_parms.collision_list = NULL; + } + + printf("ic: %d\n", ic); + rounds++; + } + while(result && (CLOTH_MAX_THRESHOLD>rounds)); + + printf("\n"); + + //////////////////////////////////////////////////////////// + // update positions + // this is needed for bvh_calc_DOP_hull_moving() [kdop.c] + //////////////////////////////////////////////////////////// + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + //////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////// + // moving collisions + //////////////////////////////////////////////////////////// + + + // update cloth bvh + bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING + + // update moving bvh for collision object once + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + if (!coll_clmd) + continue; + + if(!coll_clmd->clothObject) + continue; + + // if collision object go on + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + bvh_update(coll_clmd, coll_bvh, 1); // 0 means STATIC, 1 means MOVING + } + } + + + do + { + result = 0; + ic = 0; + clmd->coll_parms.collision_list = NULL; + + // check all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject && coll_clmd->clothObject->tree) + { + BVH *coll_bvh = coll_clmd->clothObject->tree; + + bvh_traverse(clmd, coll_clmd, cloth_bvh->root, coll_bvh->root, step, cloth_collision_moving); + } + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // process all collisions (calculate impulses, TODO: also repulses if distance too short) + result = 1; + for(j = 0; j < 10; j++) // 10 is just a value that ensures convergence + { + result = 0; + + // handle all collision objects + for (base = G.scene->base.first; base; base = base->next) + { + + coll_ob = base->object; + coll_clmd = (ClothModifierData *) modifiers_findByType (coll_ob, eModifierType_Cloth); + + if (!coll_clmd) + continue; + + // if collision object go on + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + if (coll_clmd->clothObject) + result += cloth_collision_response_moving_tris(clmd, coll_clmd); + else + printf ("cloth_bvh_objcollision: found a collision object with clothObject or collData NULL.\n"); + } + } + + // apply impulses in parallel + ic=0; + for(i = 0; i < numverts; i++) + { + // calculate "velocities" (just xnew = xold + v; no dt in v) + if(verts[i].impulse_count) + { + VECADDMUL(verts[i].tv, verts[i].impulse, 1.0f / verts[i].impulse_count); + VECCOPY(verts[i].impulse, tnull); + verts[i].impulse_count = 0; + + ic++; + ret++; + } + } + } + + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + + // update cloth bvh + bvh_update(clmd, cloth_bvh, 1); // 0 means STATIC, 1 means MOVING + + + // free collision list + if(clmd->coll_parms.collision_list) + { + LinkNode *search = clmd->coll_parms.collision_list; + while(search) + { + CollPair *coll_pair = search->link; + + MEM_freeN(coll_pair); + search = search->next; + } + BLI_linklist_free(clmd->coll_parms.collision_list,NULL); + + clmd->coll_parms.collision_list = NULL; + } + + printf("ic: %d\n", ic); + rounds++; + } + while(result && (CLOTH_MAX_THRESHOLD>rounds)); + + + //////////////////////////////////////////////////////////// + // update positions + velocities + //////////////////////////////////////////////////////////// + + // verts come from clmd + for(i = 0; i < numverts; i++) + { + VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + } + //////////////////////////////////////////////////////////// + + return MIN2(ret, 1); +} diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index a1d60b34125..b154cb0e755 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -46,11 +46,9 @@ #include "DNA_lattice_types.h" #include "DNA_scene_types.h" #include "DNA_modifier_types.h" -#include "BLI_arithb.h" #include "BLI_blenlib.h" -#include "BLI_edgehash.h" +#include "BLI_arithb.h" #include "BLI_threads.h" -#include "BKE_collisions.h" #include "BKE_curve.h" #include "BKE_displist.h" #include "BKE_effect.h" @@ -63,7 +61,6 @@ #include "BKE_global.h" #include "BIF_editdeform.h" -#include "Bullet-C-Api.h" #ifdef _WIN32 #include <windows.h> @@ -85,14 +82,18 @@ void itend(void) double itval() { return ((double)_itend.QuadPart - - (double)_itstart.QuadPart)/((double)ifreq.QuadPart); + (double)_itstart.QuadPart)/((double)ifreq.QuadPart); } #else #include <sys/time.h> +// intrinsics need better compile flag checking +// #include <xmmintrin.h> +// #include <pmmintrin.h> +// #include <pthread.h> - static struct timeval _itstart, _itend; - static struct timezone itz; - void itstart(void) +static struct timeval _itstart, _itend; +static struct timezone itz; +void itstart(void) { gettimeofday(&_itstart, &itz); } @@ -108,7 +109,14 @@ double itval() return t2-t1; } #endif - +/* +#define C99 +#ifdef C99 +#defineDO_INLINE inline +#else +#defineDO_INLINE static +#endif +*/ struct Cloth; ////////////////////////////////////////// @@ -172,7 +180,7 @@ void print_fvector(float m3[3]) // long float vector float (*)[3] /////////////////////////// /* print long vector on console: for debug output */ -DO_INLINE void print_lfvector(lfVector *fLongVector, unsigned int verts) +DO_INLINE void print_lfvector(float (*fLongVector)[3], unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -188,7 +196,7 @@ DO_INLINE lfVector *create_lfvector(unsigned int verts) // return (lfVector *)cloth_aligned_malloc(&MEMORY_BASE, verts * sizeof(lfVector)); } /* delete long vector */ -DO_INLINE void del_lfvector(lfVector *fLongVector) +DO_INLINE void del_lfvector(float (*fLongVector)[3]) { if (fLongVector != NULL) { @@ -202,7 +210,7 @@ DO_INLINE void cp_lfvector(float (*to)[3], float (*from)[3], unsigned int verts) memcpy(to, from, verts * sizeof(lfVector)); } /* init long vector with float[3] */ -DO_INLINE void init_lfvector(lfVector *fLongVector, float vector[3], unsigned int verts) +DO_INLINE void init_lfvector(float (*fLongVector)[3], float vector[3], unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -216,7 +224,7 @@ DO_INLINE void zero_lfvector(float (*to)[3], unsigned int verts) memset(to, 0.0f, verts * sizeof(lfVector)); } /* multiply long vector with scalar*/ -DO_INLINE void mul_lfvectorS(float (*to)[3], lfVector *fLongVector, float scalar, unsigned int verts) +DO_INLINE void mul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts) { unsigned int i = 0; @@ -227,7 +235,7 @@ DO_INLINE void mul_lfvectorS(float (*to)[3], lfVector *fLongVector, float scalar } /* multiply long vector with scalar*/ /* A -= B * float */ -DO_INLINE void submul_lfvectorS(float (*to)[3], lfVector *fLongVector, float scalar, unsigned int verts) +DO_INLINE void submul_lfvectorS(float (*to)[3], float (*fLongVector)[3], float scalar, unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -236,12 +244,12 @@ DO_INLINE void submul_lfvectorS(float (*to)[3], lfVector *fLongVector, float sca } } /* dot product for big vector */ -DO_INLINE float dot_lfvector(lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) +DO_INLINE float dot_lfvector(float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) { unsigned int i = 0; float temp = 0.0; // schedule(guided, 2) -#pragma omp parallel for reduction(+: temp) private(i) +#pragma omp parallel for reduction(+: temp) for(i = 0; i < verts; i++) { temp += INPR(fLongVectorA[i], fLongVectorB[i]); @@ -249,7 +257,7 @@ DO_INLINE float dot_lfvector(lfVector *fLongVectorA, lfVector *fLongVectorB, uns return temp; } /* A = B + C --> for big vector */ -DO_INLINE void add_lfvector_lfvector(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) +DO_INLINE void add_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) { unsigned int i = 0; @@ -260,7 +268,7 @@ DO_INLINE void add_lfvector_lfvector(float (*to)[3], lfVector *fLongVectorA, lfV } /* A = B + C * float --> for big vector */ -DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) +DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts) { unsigned int i = 0; @@ -271,7 +279,7 @@ DO_INLINE void add_lfvector_lfvectorS(float (*to)[3], lfVector *fLongVectorA, lf } } /* A = B * float + C * float --> for big vector */ -DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], lfVector *fLongVectorA, float aS, lfVector *fLongVectorB, float bS, unsigned int verts) +DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float aS, float (*fLongVectorB)[3], float bS, unsigned int verts) { unsigned int i = 0; @@ -281,7 +289,7 @@ DO_INLINE void add_lfvectorS_lfvectorS(float (*to)[3], lfVector *fLongVectorA, f } } /* A = B - C * float --> for big vector */ -DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, float bS, unsigned int verts) +DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], float bS, unsigned int verts) { unsigned int i = 0; for(i = 0; i < verts; i++) @@ -291,7 +299,7 @@ DO_INLINE void sub_lfvector_lfvectorS(float (*to)[3], lfVector *fLongVectorA, lf } /* A = B - C --> for big vector */ -DO_INLINE void sub_lfvector_lfvector(float (*to)[3], lfVector *fLongVectorA, lfVector *fLongVectorB, unsigned int verts) +DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts) { unsigned int i = 0; @@ -323,7 +331,7 @@ DO_INLINE void cp_fmatrix(float to[3][3], float from[3][3]) DO_INLINE float det_fmatrix(float m[3][3]) { return m[0][0]*m[1][1]*m[2][2] + m[1][0]*m[2][1]*m[0][2] + m[0][1]*m[1][2]*m[2][0] - -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2]; + -m[0][0]*m[1][2]*m[2][1] - m[0][1]*m[1][0]*m[2][2] - m[2][0]*m[1][1]*m[0][2]; } DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3]) { @@ -561,38 +569,35 @@ DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) /* SPARSE SYMMETRIC multiply big matrix with long vector*/ /* STATUS: verified */ -DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector) +DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*fLongVector)[3]) { unsigned int i = 0; - lfVector *temp = create_lfvector(from[0].vcount); - zero_lfvector(to, from[0].vcount); + /* process diagonal elements */ + for(i = 0; i < from[0].vcount; i++) + { + muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); + } -#pragma omp parallel sections private(i) + /* process off-diagonal entries (every off-diagonal entry needs to be symmetric) */ + // TODO: pragma below is wrong, correct it! + // #pragma omp parallel for shared(to,from, fLongVector) private(i) + for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) { -#pragma omp section - { - for(i = from[0].vcount; i < from[0].vcount+from[0].scount; i++) - { - muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); - } - } -#pragma omp section - { - for(i = 0; i < from[0].vcount+from[0].scount; i++) - { - muladd_fmatrix_fvector(temp[from[i].r], from[i].m, fLongVector[from[i].c]); - } - } + // muladd_fmatrix_fvector(to[from[i].c], from[i].m, fLongVector[from[i].r]); + + to[from[i].c][0] += INPR(from[i].m[0],fLongVector[from[i].r]); + to[from[i].c][1] += INPR(from[i].m[1],fLongVector[from[i].r]); + to[from[i].c][2] += INPR(from[i].m[2],fLongVector[from[i].r]); + + // muladd_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); + + to[from[i].r][0] += INPR(from[i].m[0],fLongVector[from[i].c]); + to[from[i].r][1] += INPR(from[i].m[1],fLongVector[from[i].c]); + to[from[i].r][2] += INPR(from[i].m[2],fLongVector[from[i].c]); } - add_lfvector_lfvector(to, to, temp, from[0].vcount); - - del_lfvector(temp); - - } - /* SPARSE SYMMETRIC multiply big matrix with long vector (for diagonal preconditioner) */ /* STATUS: verified */ DO_INLINE void mul_prevfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector) @@ -699,7 +704,7 @@ static float I[3][3] = {{1,0,0},{0,1,0},{0,0,1}}; static float ZERO[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}; typedef struct Implicit_Data { - lfVector *X, *V, *Xnew, *Vnew, *F, *B, *dV, *z; + lfVector *X, *V, *Xnew, *Vnew, *olddV, *F, *B, *dV, *z; fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI; } Implicit_Data; @@ -735,6 +740,8 @@ int implicit_init (Object *ob, ClothModifierData *clmd) id->Xnew = create_lfvector(cloth->numverts); id->V = create_lfvector(cloth->numverts); id->Vnew = create_lfvector(cloth->numverts); + id->olddV = create_lfvector(cloth->numverts); + zero_lfvector(id->olddV, cloth->numverts); id->F = create_lfvector(cloth->numverts); id->B = create_lfvector(cloth->numverts); id->dV = create_lfvector(cloth->numverts); @@ -767,7 +774,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) // dFdV_start[i].c = big_I[i].c = big_zero[i].c = id->A[i+cloth->numverts].c = id->dFdV[i+cloth->numverts].c = id->dFdX[i+cloth->numverts].c = - id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = spring->kl; + id->P[i+cloth->numverts].c = id->Pinv[i+cloth->numverts].c = id->bigI[i+cloth->numverts].c = spring->kl; spring->matrix_index = i + cloth->numverts; @@ -776,7 +783,7 @@ int implicit_init (Object *ob, ClothModifierData *clmd) for(i = 0; i < cloth->numverts; i++) { - VECCOPY(id->X[i], cloth->x[i]); + VECCOPY(id->X[i], verts[i].x); } return 1; @@ -805,6 +812,7 @@ int implicit_free (ClothModifierData *clmd) del_lfvector(id->Xnew); del_lfvector(id->V); del_lfvector(id->Vnew); + del_lfvector(id->olddV); del_lfvector(id->F); del_lfvector(id->B); del_lfvector(id->dV); @@ -817,31 +825,6 @@ int implicit_free (ClothModifierData *clmd) return 1; } -void cloth_bending_mode(ClothModifierData *clmd, int enabled) -{ - Cloth *cloth = clmd->clothObject; - Implicit_Data *id; - - if(cloth) - { - id = cloth->implicit; - - if(id) - { - if(enabled) - { - cloth->numsprings = cloth->numspringssave; - } - else - { - cloth->numsprings = cloth->numothersprings; - } - - id->A[0].scount = id->dFdV[0].scount = id->dFdX[0].scount = id->P[0].scount = id->Pinv[0].scount = id->bigI[0].scount = cloth->numsprings; - } - } -} - DO_INLINE float fb(float length, float L) { float x = length/L; @@ -892,7 +875,7 @@ DO_INLINE void filter(lfVector *V, fmatrix3x3 *S) } } -int cg_filtered(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) +int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S) { // Solves for unknown X in equation AX=B unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100; @@ -905,14 +888,14 @@ int cg_filtered(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix tmp = create_lfvector(numverts); r = create_lfvector(numverts); - // zero_lfvector(dv, CLOTHPARTICLES); - filter(dv, S); + // zero_lfvector(ldV, CLOTHPARTICLES); + filter(ldV, S); - add_lfvector_lfvector(dv, dv, z, numverts); + add_lfvector_lfvector(ldV, ldV, z, numverts); // r = B - Mul(tmp,A,X); // just use B if X known to be zero cp_lfvector(r, lB, numverts); - mul_bfmatrix_lfvector(tmp, lA, dv); + mul_bfmatrix_lfvector(tmp, lA, ldV); sub_lfvector_lfvector(r, r, tmp, numverts); filter(r,S); @@ -932,7 +915,7 @@ int cg_filtered(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix a = s/dot_lfvector(d, q, numverts); // X = X + d*a; - add_lfvector_lfvectorS(dv, dv, d, a, numverts); + add_lfvector_lfvectorS(ldV, ldV, d, a, numverts); // r = r - q*a; sub_lfvector_lfvectorS(r, r, q, a, numverts); @@ -947,16 +930,12 @@ int cg_filtered(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix conjgrad_loopcount++; } - // itend(); - // printf("cg_filtered time: %f\n", (float)itval()); - conjgrad_lasterror = s; del_lfvector(q); del_lfvector(d); del_lfvector(tmp); del_lfvector(r); - // printf("W/O conjgrad_loopcount: %d\n", conjgrad_loopcount); return conjgrad_loopcount<conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable @@ -1101,13 +1080,15 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float vel[3]; float k = 0.0f; float L = s->restlen; - float cb = clmd->sim_parms->structural; + float cb = clmd->sim_parms.structural; float nullf[3] = {0,0,0}; float stretch_force[3] = {0,0,0}; float bending_force[3] = {0,0,0}; float damping_force[3] = {0,0,0}; float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}}; + Cloth *cloth = clmd->clothObject; + ClothVertex *verts = cloth->verts; VECCOPY(s->f, nullf); cp_fmatrix(s->dfdx, nulldfdx); @@ -1125,13 +1106,13 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, /* if(length>L) { - if((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) - && ((((length-L)*100.0f/L) > clmd->sim_parms->maxspringlen))) // cut spring! - { - s->flags |= CSPRING_FLAG_DEACTIVATE; - return; - } - } + if((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) + && ((((length-L)*100.0f/L) > clmd->sim_parms.maxspringlen))) // cut spring! + { + s->flags |= CSPRING_FLAG_DEACTIVATE; + return; + } + } */ mul_fvector_S(dir, extent, 1.0f/length); } @@ -1141,19 +1122,6 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, } - /* - if(s->type == CLOTH_SPRING_TYPE_COLLISION) - { - if(length < L) - { - mul_fvector_S(stretch_force, dir, (100.0*(length-L))); - - VECADD(s->f, s->f, stretch_force); - } - return; - } - */ - // calculate force of structural + shear springs if(s->type != CLOTH_SPRING_TYPE_BENDING) { @@ -1161,72 +1129,56 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, { s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = clmd->sim_parms->structural; + k = clmd->sim_parms.structural; mul_fvector_S(stretch_force, dir, (k*(length-L))); VECADD(s->f, s->f, stretch_force); // Ascher & Boxman, p.21: Damping only during elonglation - mul_fvector_S(damping_force, extent, clmd->sim_parms->Cdis * 0.01 * ((INPR(vel,extent)/length))); + mul_fvector_S(damping_force, extent, clmd->sim_parms.Cdis * ((INPR(vel,extent)/length))); VECADD(s->f, s->f, damping_force); dfdx_spring_type1(s->dfdx, dir,length,L,k); - dfdv_damp(s->dfdv, dir,clmd->sim_parms->Cdis); + dfdv_damp(s->dfdv, dir,clmd->sim_parms.Cdis); } } else // calculate force of bending springs { if(length < L) { - // clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; - s->flags |= CLOTH_SPRING_FLAG_NEEDED; - k = clmd->sim_parms->bending; + k = clmd->sim_parms.bending; mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb)); VECADD(s->f, s->f, bending_force); - - // if(INPR(bending_force,bending_force) > 0.13*0.13) - { - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; - } - - + dfdx_spring_type2(s->dfdx, dir,length,L,k, cb); - /* - if(s->ij == 300 || s->kl == 300) - printf("id->F[0]: %f, id->F[1]: %f, id->F[2]: %f\n", s->f[0], s->f[1], s->f[2]); - */ } } } -DO_INLINE int cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) +DO_INLINE void cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX) { if(s->flags & CLOTH_SPRING_FLAG_NEEDED) { - VECADD(lF[s->ij], lF[s->ij], s->f); - VECSUB(lF[s->kl], lF[s->kl], s->f); - if(s->type != CLOTH_SPRING_TYPE_BENDING) { sub_fmatrix_fmatrix(dFdV[s->ij].m, dFdV[s->ij].m, s->dfdv); sub_fmatrix_fmatrix(dFdV[s->kl].m, dFdV[s->kl].m, s->dfdv); - add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); + add_fmatrix_fmatrix(dFdV[s->matrix_index].m, dFdV[s->matrix_index].m, s->dfdv); } - else if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE)) - return 0; - + + VECADD(lF[s->ij], lF[s->ij], s->f); + VECSUB(lF[s->kl], lF[s->kl], s->f); + sub_fmatrix_fmatrix(dFdX[s->ij].m, dFdX[s->ij].m, s->dfdx); sub_fmatrix_fmatrix(dFdX[s->kl].m, dFdX[s->kl].m, s->dfdx); add_fmatrix_fmatrix(dFdX[s->matrix_index].m, dFdX[s->matrix_index].m, s->dfdx); - } - - return 1; + } } DO_INLINE void calculateTriangleNormal(float to[3], lfVector *X, MFace mface) @@ -1275,7 +1227,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec /* Collect forces and derivatives: F,dFdX,dFdV */ Cloth *cloth = clmd->clothObject; unsigned int i = 0; - float spring_air = clmd->sim_parms->Cvi * 0.01f; /* viscosity of air scaled in percent */ + float spring_air = clmd->sim_parms.Cvi * 0.01f; /* viscosity of air scaled in percent */ float gravity[3]; float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}}; ClothVertex *verts = cloth->verts; @@ -1286,7 +1238,8 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float kd, ks; LinkNode *search = cloth->springs; - VECCOPY(gravity, clmd->sim_parms->gravity); + + VECCOPY(gravity, clmd->sim_parms.gravity); mul_fvector_S(gravity, gravity, 0.001f); /* scale gravity force */ /* set dFdX jacobi matrix to zero */ @@ -1299,24 +1252,24 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec submul_lfvectorS(lF, lV, spring_air, numverts); /* do goal stuff */ - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { for(i = 0; i < numverts; i++) { if(verts [i].goal < SOFTGOALSNAP) { // current_position = xold + t * (newposition - xold) - VECSUB(tvect, cloth->xconst[i], cloth->xold[i]); + VECSUB(tvect, verts[i].xconst, verts[i].xold); mul_fvector_S(tvect, tvect, time); - VECADD(tvect, tvect, cloth->xold[i]); + VECADD(tvect, tvect, verts[i].xold); VECSUB(auxvect, tvect, lX[i]); - ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms->goalspring)-1.0f ; + ks = 1.0f/(1.0f- verts [i].goal*clmd->sim_parms.goalspring)-1.0f ; VECADDS(lF[i], lF[i], auxvect, -ks); // calulate damping forces generated by goals - VECSUB(velgoal, cloth->xold[i], cloth->xconst[i]); - kd = clmd->sim_parms->goalfrict * 0.01f; // friction force scale taken from SB + VECSUB(velgoal,verts[i].xold, verts[i].xconst); + kd = clmd->sim_parms.goalfrict * 0.01f; // friction force scale taken from SB VECSUBADDSS(lF[i], velgoal, kd, lV[i], kd); } @@ -1329,7 +1282,7 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float speed[3] = {0.0f, 0.0f,0.0f}; float force[3]= {0.0f, 0.0f, 0.0f}; -// #pragma omp parallel for private (i) shared(lF) + #pragma omp parallel for private (i) shared(lF) for(i = 0; i < cloth->numverts; i++) { float vertexnormal[3]={0,0,0}; @@ -1353,42 +1306,24 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec while(search) { // only handle active springs - // if(((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)){} + // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)){} cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); search = search->next; } - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_BIG_FORCE) - { - if(cloth->numspringssave != cloth->numsprings) - { - cloth_bending_mode(clmd, 1); - } - } - else - { - if(cloth->numspringssave == cloth->numsprings) - { - cloth_bending_mode(clmd, 0); - } - } - // apply spring forces search = cloth->springs; while(search) { // only handle active springs - // if(((clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms->flags & CSIMSETT_FLAG_TEARING_ENABLED)) - if(!cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX)) - break; + // if(((clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED) && !(springs[i].flags & CSPRING_FLAG_DEACTIVATE))|| !(clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)) + cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX); search = search->next; } - - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_BIG_FORCE; } -void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, fmatrix3x3 *P, fmatrix3x3 *Pinv) +void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVector *lF, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, float dt, fmatrix3x3 *A, lfVector *B, lfVector *dV, fmatrix3x3 *S, lfVector *z, lfVector *olddV, fmatrix3x3 *P, fmatrix3x3 *Pinv) { unsigned int numverts = dFdV[0].vcount; @@ -1396,46 +1331,48 @@ void simulate_implicit_euler(lfVector *Vnew, lfVector *lX, lfVector *lV, lfVecto initdiag_bfmatrix(A, I); zero_lfvector(dV, numverts); - subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); + subadd_bfmatrixS_bfmatrixS(A, dFdV, dt, dFdX, (dt*dt)); + mul_bfmatrix_lfvector(dFdXmV, dFdX, lV); + add_lfvectorS_lfvectorS(B, lF, dt, dFdXmV, (dt*dt), numverts); - // TODO: unstable with quality=5 + stiffness=7000 + no zero_lfvector() + itstart(); + cg_filtered(dV, A, B, z, S); /* conjugate gradient algorithm to solve Ax=b */ + // cg_filtered_pre(dV, A, B, z, olddV, P, Pinv, dt); - // TODO: unstable with quality=5 + stiffness=7000 - // cg_filtered_pre(dV, A, B, z, S, P, Pinv); + itend(); + // printf("cg_filtered calc time: %f\n", (float)itval()); + cp_lfvector(olddV, dV, numverts); + // advance velocities add_lfvector_lfvector(Vnew, lV, dV, numverts); + del_lfvector(dFdXmV); } int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors) -{ - unsigned int i=0; +{ + unsigned int i=0, j; float step=0.0f, tf=1.0f; Cloth *cloth = clmd->clothObject; ClothVertex *verts = cloth->verts; unsigned int numverts = cloth->numverts; - float dt = 1.0f / clmd->sim_parms->stepsPerFrame; + float dt = 1.0f / clmd->sim_parms.stepsPerFrame; Implicit_Data *id = cloth->implicit; int result = 0; - float force = 0, lastforce = 0; - // lfVector *dx; - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { for(i = 0; i < numverts; i++) { // update velocities with constrained velocities from pinned verts if(verts [i].goal >= SOFTGOALSNAP) { - float temp[3]; - VECSUB(temp, cloth->xconst[i], cloth->xold[i]); - VECSUB(id->z[i], temp, id->V[i]); - + VECSUB(id->V[i], verts[i].xconst, verts[i].xold); // VecMulf(id->V[i], 1.0 / dt); } } @@ -1445,43 +1382,13 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase { effectors= pdInitEffectors(ob,NULL); - // clear constraint matrix from collisions - if(clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) - { - for(i = 0; i < id->S[0].vcount; i++) - { - if(!(verts [id->S[i].r].goal >= SOFTGOALSNAP)) - { - id->S[0].vcount = i-1; - break; - } - } - } - // calculate - cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); + cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step ); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); - // check for sleeping - // if(!(clmd->coll_parms->flags & CLOTH_SIMSETTINGS_FLAG_SLEEP)) - { - simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt, id->A, id->B, id->dV, id->S, id->z, id->P, id->Pinv); + add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); - add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts); - } - /* - dx = create_lfvector(numverts); - sub_lfvector_lfvector(dx, id->Xnew, id->X, numverts); - force = dot_lfvector(dx, dx, numverts); - del_lfvector(dx); - - if((force < 0.00001) && (lastforce >= force)) - clmd->coll_parms->flags |= CLOTH_SIMSETTINGS_FLAG_SLEEP; - else if((lastforce*2 < force)) - clmd->coll_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_SLEEP; - */ - lastforce = force; - - if(clmd->coll_parms->flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) + if(clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED) { // collisions // itstart(); @@ -1489,42 +1396,46 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // update verts to current positions for(i = 0; i < numverts; i++) { - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) /* do goal stuff */ { if(verts [i].goal >= SOFTGOALSNAP) { float tvect[3] = {.0,.0,.0}; // VECSUB(tvect, id->Xnew[i], verts[i].xold); mul_fvector_S(tvect, id->V[i], step+dt); - VECADD(tvect, tvect, cloth->xold[i]); + VECADD(tvect, tvect, verts[i].xold); VECCOPY(id->Xnew[i], tvect); } } - VECCOPY(cloth->current_x[i], id->Xnew[i]); - VECSUB(cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i]); - VECCOPY(cloth->v[i], cloth->current_v[i]); + VECCOPY(verts[i].tx, id->Xnew[i]); + + VECSUB(verts[i].tv, verts[i].tx, verts[i].txold); + VECCOPY(verts[i].v, verts[i].tv); } - + // call collision function - result = cloth_bvh_objcollision(clmd, step + dt, step, dt); - + result = cloth_bvh_objcollision(clmd, step + dt, dt); + // copy corrected positions back to simulation - if(result) - { - memcpy(cloth->current_xold, cloth->current_x, sizeof(lfVector) * numverts); - memcpy(id->Xnew, cloth->current_x, sizeof(lfVector) * numverts); - - for(i = 0; i < numverts; i++) - { - VECCOPY(id->Vnew[i], cloth->current_v[i]); + for(i = 0; i < numverts; i++) + { + if(result) + { + // VECADD(verts[i].tx, verts[i].txold, verts[i].tv); + + VECCOPY(verts[i].txold, verts[i].tx); + + VECCOPY(id->Xnew[i], verts[i].tx); + + VECCOPY(id->Vnew[i], verts[i].tv); VecMulf(id->Vnew[i], 1.0f / dt); } - } - else - { - memcpy(cloth->current_xold, id->Xnew, sizeof(lfVector) * numverts); + else + { + VECCOPY(verts[i].txold, id->Xnew[i]); + } } // X = Xnew; @@ -1538,9 +1449,8 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // calculate cloth_calc_force(clmd, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step); - simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->P, id->Pinv); + simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv); } - } else { @@ -1553,817 +1463,49 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase // V = Vnew; cp_lfvector(id->V, id->Vnew, numverts); - + step += dt; if(effectors) pdEndEffectors(effectors); } - - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - { - for(i = 0; i < numverts; i++) + + for(i = 0; i < numverts; i++) + { + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) { if(verts [i].goal < SOFTGOALSNAP) { - VECCOPY(cloth->current_xold[i], id->X[i]); - VECCOPY(cloth->x[i], id->X[i]); + VECCOPY(verts[i].txold, id->X[i]); + VECCOPY(verts[i].x, id->X[i]); + VECCOPY(verts[i].v, id->V[i]); } else { - VECCOPY(cloth->current_xold[i], cloth->xconst[i]); - VECCOPY(cloth->x[i], cloth->xconst[i]); + VECCOPY(verts[i].txold, verts[i].xconst); + VECCOPY(verts[i].x, verts[i].xconst); + VECCOPY(verts[i].v, id->V[i]); } } + else + { + VECCOPY(verts[i].txold, id->X[i]); + VECCOPY(verts[i].x, id->X[i]); + VECCOPY(verts[i].v, id->V[i]); + } } - else - { - memcpy(cloth->current_xold, id->X, sizeof(lfVector) * numverts); - memcpy(cloth->x, id->X, sizeof(lfVector) * numverts); - } - - memcpy(cloth->v, id->V, sizeof(lfVector) * numverts); - return 1; } void implicit_set_positions (ClothModifierData *clmd) { Cloth *cloth = clmd->clothObject; - unsigned int numverts = cloth->numverts; - Implicit_Data *id = cloth->implicit; - - memcpy(id->X, cloth->x, sizeof(lfVector) * numverts); - memcpy(id->V, cloth->v, sizeof(lfVector) * numverts); -} - -unsigned int implicit_getcreate_S_index(ClothModifierData *clmd, unsigned int index) -{ - Cloth *cloth = clmd->clothObject; + ClothVertex *verts = cloth->verts; + unsigned int numverts = cloth->numverts, i; Implicit_Data *id = cloth->implicit; - unsigned int i = 0, pinned = 0; - - pinned = id->S[0].vcount; - - for(i = 0; i < pinned; i++) - { - if(id->S[i].r == index) - { - return index; - } - } - - // create new PINNED entry in constraint matrix - id->S[0].vcount++; - id->S[pinned].c = id->S[pinned].r = index; - return pinned; -} - -int collisions_collision_response_static ( ClothModifierData *clmd, CollisionModifierData *collmd, CollisionPair *collpair ) -{ - - unsigned int i = 0; - int result = 0; - LinkNode *search = NULL; - Cloth *cloth1 = NULL; - float w1, w2, w3, u1, u2, u3; - float v1[3], v2[3], relativeVelocity[3]; - float magrelVel = 0.0; - float epsilon = clmd->coll_parms->epsilon; - - - cloth1 = clmd->clothObject; - - if(!collpair) - { - return 0; - } - - // TODO: check distance & calc normal - // calc distance + normal - collpair->distance = plNearestPoints( - cloth1->current_xold[collpair->point_indexA[0]], - cloth1->current_xold[collpair->point_indexA[1]], - cloth1->current_xold[collpair->point_indexA[2]], - collmd->current_x[collpair->point_indexB[0]].co, - collmd->current_x[collpair->point_indexB[1]].co, - collmd->current_x[collpair->point_indexB[2]].co, - collpair->pa,collpair->pb,collpair->vector); - - if (collpair->distance > (epsilon + ALMOST_ZERO)) - { - printf("collpair->distance > (epsilon + ALMOST_ZERO)\n"); - return 0; - } - - printf("IN1\n"); - - // compute barycentric coordinates for both collision points - collisions_compute_barycentric (collpair->pa, - cloth1->current_xold[collpair->point_indexA[0]], - cloth1->current_xold[collpair->point_indexA[1]], - cloth1->current_xold[collpair->point_indexA[2]], - &w1, &w2, &w3 ); - - collisions_compute_barycentric (collpair->pb, - collmd->current_x[collpair->point_indexB[0]].co, - collmd->current_x[collpair->point_indexB[1]].co, - collmd->current_x[collpair->point_indexB[2]].co, - &u1, &u2, &u3 ); - - // Calculate relative "velocity". - interpolateOnTriangle ( v1, cloth1->current_v[collpair->point_indexA[0]], cloth1->current_v[collpair->point_indexA[1]], cloth1->current_v[collpair->point_indexA[2]], w1, w2, w3 ); - - interpolateOnTriangle ( v2, collmd->current_v[collpair->point_indexB[0]].co, collmd->current_v[collpair->point_indexB[1]].co, collmd->current_v[collpair->point_indexB[2]].co, u1, u2, u3 ); - - VECSUB ( relativeVelocity, v1, v2 ); - - // Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). - magrelVel = INPR ( relativeVelocity, collpair->normal ); - - // printf("magrelVel: %f\n", magrelVel); - - // Calculate masses of points. - - // If v_n_mag < 0 the edges are approaching each other. - if ( magrelVel < -ALMOST_ZERO ) - { - - // Calculate Impulse magnitude to stop all motion in normal direction. - // const double I_mag = v_n_mag / (1/m1 + 1/m2); - float magnitude_i = magrelVel / 2.0f; // TODO implement masses - float tangential[3], magtangent, magnormal, collvel[3]; - float vrel_t_pre[3]; - float vrel_t[3]; - double impulse; - float overlap = ( epsilon + ALMOST_ZERO-collpair->distance ); - - printf("magrelVel < -ALMOST_ZERO\n"); - - // calculateFrictionImpulse(tangential, relativeVelocity, collpair->normal, magrelVel, clmd->coll_parms.friction*0.01, magrelVel); - - // magtangent = INPR(tangential, tangential); - - // Apply friction impulse. - if ( magtangent < -ALMOST_ZERO ) - { - - // printf("friction applied: %f\n", magtangent); - // TODO check original code - } - - - impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 ); - - // printf("impulse: %f\n", impulse); - - // face A - VECADDMUL ( cloth1->verts[collpair->point_indexA[0]].impulse, collpair->normal, w1 * impulse ); - cloth1->verts[collpair->point_indexA[0]].impulse_count++; - - VECADDMUL ( cloth1->verts[collpair->point_indexA[1]].impulse, collpair->normal, w2 * impulse ); - cloth1->verts[collpair->point_indexA[1]].impulse_count++; - - VECADDMUL ( cloth1->verts[collpair->point_indexA[2]].impulse, collpair->normal, w3 * impulse ); - cloth1->verts[collpair->point_indexA[2]].impulse_count++; - - // face B - /* - VECADDMUL ( collmd->verts[collpair->point_indexB[0]].impulse, collpair->normal, u1 * impulse ); - collmd->verts[collpair->point_indexB[0]].impulse_count++; - - VECADDMUL ( collmd->verts[collpair->point_indexB[1]].impulse, collpair->normal, u2 * impulse ); - collmd->verts[collpair->point_indexB[1]].impulse_count++; - - VECADDMUL ( collmd->verts[collpair->point_indexB[2]].impulse, collpair->normal, u3 * impulse ); - collmd->verts[collpair->point_indexB[2]].impulse_count++; - */ - - - result = 1; - - // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case - - // Apply the impulse and increase impulse counters. - - } - - return result; -} - - -int collisions_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd) -{ - return 0; -} - - -int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd) -{ - return 0; -} - -void cloth_collision_static(ClothModifierData *clmd, LinkNode *collision_list) -{ - /* - CollPair *collpair = NULL; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; - double distance = 0; - float epsilon = clmd->coll_parms->epsilon; - unsigned int i = 0; - - for(i = 0; i < 4; i++) - { - collpair = (CollPair *)MEM_callocN(sizeof(CollPair), "cloth coll pair"); - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); - - // check all possible pairs of triangles - if(i == 0) - { - collpair->ap1 = face1->v1; - collpair->ap2 = face1->v2; - collpair->ap3 = face1->v3; - - collpair->bp1 = face2->v1; - collpair->bp2 = face2->v2; - collpair->bp3 = face2->v3; - -} - - if(i == 1) - { - if(face1->v4) - { - collpair->ap1 = face1->v3; - collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; - - collpair->bp1 = face2->v1; - collpair->bp2 = face2->v2; - collpair->bp3 = face2->v3; -} - else - i++; -} - - if(i == 2) - { - if(face2->v4) - { - collpair->ap1 = face1->v1; - collpair->ap2 = face1->v2; - collpair->ap3 = face1->v3; - - collpair->bp1 = face2->v3; - collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; -} - else - i+=2; -} - - if(i == 3) - { - if((face1->v4)&&(face2->v4)) - { - collpair->ap1 = face1->v3; - collpair->ap2 = face1->v4; - collpair->ap3 = face1->v1; - - collpair->bp1 = face2->v3; - collpair->bp2 = face2->v4; - collpair->bp3 = face2->v1; -} - else - i++; -} - - - if(i < 4) - { - // calc distance + normal - distance = plNearestPoints( - verts1[collpair->ap1].txold, verts1[collpair->ap2].txold, verts1[collpair->ap3].txold, verts2[collpair->bp1].txold, verts2[collpair->bp2].txold, verts2[collpair->bp3].txold, collpair->pa,collpair->pb,collpair->vector); - - if (distance <= (epsilon + ALMOST_ZERO)) - { - // printf("dist: %f\n", (float)distance); - - // collpair->face1 = tree1->tri_index; - // collpair->face2 = tree2->tri_index; - - // VECCOPY(collpair->normal, collpair->vector); - // Normalize(collpair->normal); - - // collpair->distance = distance; - -} - else - { - MEM_freeN(collpair); -} -} - else - { - MEM_freeN(collpair); -} -} - */ -} - -int collisions_are_edges_adjacent(ClothModifierData *clmd, ClothModifierData *coll_clmd, EdgeCollPair *edgecollpair) -{ - Cloth *cloth1, *cloth2; - ClothVertex *verts1, *verts2; - float temp[3]; - /* - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p21].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - - VECSUB(temp, verts1[edgecollpair->p11].xold, verts2[edgecollpair->p22].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - - VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p21].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - - VECSUB(temp, verts1[edgecollpair->p12].xold, verts2[edgecollpair->p22].xold); - if(ABS(INPR(temp, temp)) < ALMOST_ZERO) - return 1; - */ - return 0; -} - - -void collisions_collision_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) -{ - /* - EdgeCollPair edgecollpair; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; - double distance = 0; - float epsilon = clmd->coll_parms->epsilon; - unsigned int i = 0, j = 0, k = 0; - int numsolutions = 0; - float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; - - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); - - for( i = 0; i < 5; i++) - { - if(i == 0) - { - edgecollpair.p11 = face1->v1; - edgecollpair.p12 = face1->v2; -} - else if(i == 1) - { - edgecollpair.p11 = face1->v2; - edgecollpair.p12 = face1->v3; -} - else if(i == 2) - { - if(face1->v4) - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v4; -} - else - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v1; - i+=5; // get out of here after this edge pair is handled -} -} - else if(i == 3) - { - if(face1->v4) - { - edgecollpair.p11 = face1->v4; - edgecollpair.p12 = face1->v1; -} - else - continue; -} - else - { - edgecollpair.p11 = face1->v3; - edgecollpair.p12 = face1->v1; -} - - - for( j = 0; j < 5; j++) - { - if(j == 0) - { - edgecollpair.p21 = face2->v1; - edgecollpair.p22 = face2->v2; -} - else if(j == 1) - { - edgecollpair.p21 = face2->v2; - edgecollpair.p22 = face2->v3; -} - else if(j == 2) - { - if(face2->v4) - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v4; -} - else - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v1; -} -} - else if(j == 3) - { - if(face2->v4) - { - edgecollpair.p21 = face2->v4; - edgecollpair.p22 = face2->v1; -} - else - continue; -} - else - { - edgecollpair.p21 = face2->v3; - edgecollpair.p22 = face2->v1; -} - - - if(!collisions_are_edges_adjacent(clmd, coll_clmd, &edgecollpair)) - { - VECSUB(a, verts1[edgecollpair.p12].xold, verts1[edgecollpair.p11].xold); - VECSUB(b, verts1[edgecollpair.p12].v, verts1[edgecollpair.p11].v); - VECSUB(c, verts1[edgecollpair.p21].xold, verts1[edgecollpair.p11].xold); - VECSUB(d, verts1[edgecollpair.p21].v, verts1[edgecollpair.p11].v); - VECSUB(e, verts2[edgecollpair.p22].xold, verts1[edgecollpair.p11].xold); - VECSUB(f, verts2[edgecollpair.p22].v, verts1[edgecollpair.p11].v); - - numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution); - - for (k = 0; k < numsolutions; k++) - { - if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) - { - float out_collisionTime = solution[k]; - - // TODO: check for collisions - - // TODO: put into (edge) collision list - - printf("Moving edge found!\n"); -} -} -} -} -} - */ -} - -void collisions_collision_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) -{ - /* - CollPair collpair; - Cloth *cloth1=NULL, *cloth2=NULL; - MFace *face1=NULL, *face2=NULL; - ClothVertex *verts1=NULL, *verts2=NULL; - double distance = 0; - float epsilon = clmd->coll_parms->epsilon; - unsigned int i = 0, j = 0, k = 0; - int numsolutions = 0; - float a[3], b[3], c[3], d[3], e[3], f[3], solution[3]; - - for(i = 0; i < 2; i++) - { - cloth1 = clmd->clothObject; - cloth2 = coll_clmd->clothObject; - - verts1 = cloth1->verts; - verts2 = cloth2->verts; - - face1 = &(cloth1->mfaces[tree1->tri_index]); - face2 = &(cloth2->mfaces[tree2->tri_index]); - - // check all possible pairs of triangles - if(i == 0) - { - collpair.ap1 = face1->v1; - collpair.ap2 = face1->v2; - collpair.ap3 = face1->v3; - - collpair.pointsb[0] = face2->v1; - collpair.pointsb[1] = face2->v2; - collpair.pointsb[2] = face2->v3; - collpair.pointsb[3] = face2->v4; -} - - if(i == 1) - { - if(face1->v4) - { - collpair.ap1 = face1->v3; - collpair.ap2 = face1->v4; - collpair.ap3 = face1->v1; - - collpair.pointsb[0] = face2->v1; - collpair.pointsb[1] = face2->v2; - collpair.pointsb[2] = face2->v3; - collpair.pointsb[3] = face2->v4; -} - else - i++; -} - - // calc SIPcode (?) - - if(i < 2) - { - VECSUB(a, verts1[collpair.ap2].xold, verts1[collpair.ap1].xold); - VECSUB(b, verts1[collpair.ap2].v, verts1[collpair.ap1].v); - VECSUB(c, verts1[collpair.ap3].xold, verts1[collpair.ap1].xold); - VECSUB(d, verts1[collpair.ap3].v, verts1[collpair.ap1].v); - - for(j = 0; j < 4; j++) - { - if((j==3) && !(face2->v4)) - break; - - VECSUB(e, verts2[collpair.pointsb[j]].xold, verts1[collpair.ap1].xold); - VECSUB(f, verts2[collpair.pointsb[j]].v, verts1[collpair.ap1].v); - - numsolutions = collisions_get_collision_time(a, b, c, d, e, f, solution); - - for (k = 0; k < numsolutions; k++) - { - if ((solution[k] >= 0.0) && (solution[k] <= 1.0)) - { - float out_collisionTime = solution[k]; - - // TODO: check for collisions - - // TODO: put into (point-face) collision list - - printf("Moving found!\n"); - -} -} - - // TODO: check borders for collisions -} - -} -} - */ -} - -void collisions_collision_moving(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *tree2) -{ - /* - // TODO: check for adjacent - collisions_collision_moving_edges(clmd, coll_clmd, tree1, tree2); - - collisions_collision_moving_tris(clmd, coll_clmd, tree1, tree2); - collisions_collision_moving_tris(coll_clmd, clmd, tree2, tree1); - */ -} - -// cloth - object collisions -int cloth_bvh_objcollision(ClothModifierData * clmd, float step, float prevstep, float dt) -{ - - Base *base = NULL; - CollisionModifierData *collmd = NULL; - Cloth *cloth = NULL; - Object *ob2 = NULL; - BVH *bvh1 = NULL, *bvh2 = NULL, *self_bvh; - LinkNode *collision_list = NULL; - unsigned int i = 0, j = 0, index; - int collisions = 0, count = 0; - float (*current_x)[3]; - Implicit_Data *id = NULL; - int ret = 0; - - if (!(((Cloth *)clmd->clothObject)->tree)) - { - printf("No BVH found\n"); - return 0; - } - - cloth = clmd->clothObject; - bvh1 = cloth->tree; - self_bvh = cloth->selftree; - id = cloth->implicit; - - //////////////////////////////////////////////////////////// - // static collisions - //////////////////////////////////////////////////////////// - - // update cloth bvh - bvh_update_from_float3 ( bvh1, cloth->current_xold, cloth->numverts, cloth->current_x, 0 ); // 0 means STATIC, 1 means MOVING (see later in this function) - - // check all collision objects - for ( base = G.scene->base.first; base; base = base->next ) - { - ob2 = base->object; - collmd = ( CollisionModifierData * ) modifiers_findByType ( ob2, eModifierType_Collision ); - - if ( !collmd ) - continue; - - // check if there is a bounding volume hierarchy - if ( collmd->tree ) - { - bvh2 = collmd->tree; - - // update position + bvh of collision object - collision_move_object ( collmd, step, prevstep ); - bvh_update_from_mvert ( collmd->tree, collmd->current_x, collmd->numverts, NULL, 0 ); - - // fill collision list - collisions += bvh_traverse ( bvh1->root, bvh2->root, &collision_list ); - - // call static collision response - if ( collision_list ) - { - LinkNode *search = collision_list; - - while ( search ) - { - collisions_collision_response_static(clmd, collmd, (CollisionPair *)search->link); - - search = search->next; - } - } - - // free collision list - if ( collision_list ) - { - LinkNode *search = collision_list; - - while ( search ) - { - CollisionPair *coll_pair = search->link; - - MEM_freeN ( coll_pair ); - search = search->next; - } - BLI_linklist_free ( collision_list,NULL ); - - collision_list = NULL; - } - } - } - - // vertex weight = 2 - - for(i = 0; i < cloth->numverts; i++) - if ((cloth->verts[i].impulse_count > 0) && !(cloth->verts[i].flags & CVERT_FLAG_PINNED)) - { - printf("applying impulse\n"); - - VECADDS(cloth->current_v[i], cloth->current_v[i], cloth->verts[i].impulse, 1.0 / (cloth->verts[i].impulse_count * 2.0)); - - // reset - cloth->verts[i].impulse_count = 0; - cloth->verts[i].impulse[0] = 0.0; - cloth->verts[i].impulse[1] = 0.0; - cloth->verts[i].impulse[2] = 0.0; - - ret = 1; - } - - ////////////////////////////////////////////// - // update velocities + positions - ////////////////////////////////////////////// - for(i = 0; i < cloth->numverts; i++) - { - VECADD(cloth->current_x[i], cloth->current_xold[i], cloth->current_v[i]); - } - ////////////////////////////////////////////// - - - // Test on *simple* selfcollisions - collisions = 1; - count = 0; - current_x = cloth->current_x; // needed for openMP - /* - // #pragma omp parallel for private(i,j, collisions) shared(current_x) - // for ( count = 0; count < 6; count++ ) - { - collisions = 0; - - for ( i = 0; i < cloth->numverts; i++ ) - { - float mindistance1 = cloth->verts[i].collball; - - for ( j = i + 1; j < cloth->numverts; j++ ) - { - float temp[3]; - float length = 0; - - float mindistance2 = cloth->verts[j].collball; - - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) - { - if ( ( cloth->verts [i].goal >= SOFTGOALSNAP ) - && ( cloth->verts [j].goal >= SOFTGOALSNAP ) ) - { - continue; - } - } - - // check for adjacent points - if ( BLI_edgehash_haskey ( cloth->edgehash, i, j ) ) - { - continue; - } - - VECSUB ( temp, current_x[i], current_x[j] ); - - length = Normalize ( temp ); - - if ( length < ((mindistance1 + mindistance2)) ) - { - float correction = ((mindistance1 + mindistance2)) - length; - - if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) && ( cloth->verts [i].goal >= SOFTGOALSNAP ) ) - { - VecMulf ( temp, -correction ); - VECADD ( current_x[j], current_x[j], temp ); - } - else if ( ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) && ( cloth->verts [j].goal >= SOFTGOALSNAP ) ) - { - VecMulf ( temp, correction ); - VECADD ( current_x[i], current_x[i], temp ); - } - else - { - unsigned int pinned = id->S[0].vcount; - - printf("correction: %f\n", correction); - - VecMulf ( temp, -correction*0.5 ); - VECADD ( current_x[j], current_x[j], temp ); - VECSUB ( cloth->current_v[j], cloth->current_x[j], cloth->current_xold[j] ); - - index = implicit_getcreate_S_index(clmd, j); - id->S[index].pinned = 1; - - VECSUB ( current_x[i], current_x[i], temp ); - VECSUB ( cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i] ); - - index = implicit_getcreate_S_index(clmd, i); - id->S[index].pinned = 1; - - cloth_add_spring (clmd, i, j, mindistance1 + mindistance2, CLOTH_SPRING_TYPE_COLLISION); - } - - collisions = 1; - } - } - } - } - */ - - ////////////////////////////////////////////// - // SELFCOLLISIONS: update velocities - ////////////////////////////////////////////// - /* - for ( i = 0; i < cloth->numverts; i++ ) - { - VECSUB ( cloth->current_v[i], cloth->current_x[i], cloth->current_xold[i] ); - } - */ - ////////////////////////////////////////////// - - return ret; + for(i = 0; i < numverts; i++) + { + VECCOPY(id->X[i], verts[i].x); + VECCOPY(id->V[i], verts[i].v); + } } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index e7ce752424d..3b69f47b1f4 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -75,7 +75,6 @@ #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" @@ -2727,7 +2726,7 @@ static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob, { DisplaceModifierData *dmd = (DisplaceModifierData*) md; - walk(userData, ob, (ID **)&dmd->texture); + walk(userData, ob, &dmd->texture); displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc) walk, userData); } @@ -4947,15 +4946,9 @@ static void softbodyModifier_deformVerts( static void clothModifier_initData(ModifierData *md) { ClothModifierData *clmd = (ClothModifierData*) md; - - clmd->sim_parms = MEM_callocN(sizeof(SimulationSettings), - "cloth sim parms"); - clmd->coll_parms = MEM_callocN(sizeof(CollisionSettings), - "cloth coll parms"); - cloth_init (clmd); } -/* + static void clothModifier_deformVerts( ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) @@ -4978,23 +4971,6 @@ static void clothModifier_deformVerts( if(dm) dm->release(dm); } -*/ - -static DerivedMesh *clothModifier_applyModifier( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - int useRenderParams, int isFinalCalc) -{ - ClothModifierData *clmd = (ClothModifierData*) md; - DerivedMesh *result=NULL; - - result = clothModifier_do(clmd, ob, derivedData, useRenderParams, isFinalCalc); - - if(result) - { - return result; - } - return derivedData; -} static void clothModifier_updateDepgraph( ModifierData *md, DagForest *forest, Object *ob, @@ -5011,13 +4987,14 @@ static void clothModifier_updateDepgraph( Object *ob1= base->object; if(ob1 != ob) { - CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision); - if(collmd) - { - DagNode *curNode = dag_get_node(forest, ob1); - - dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); - + ClothModifierData *coll_clmd = (ClothModifierData *)modifiers_findByType(ob1, eModifierType_Cloth); + if(coll_clmd) + { + if (coll_clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) + { + DagNode *curNode = dag_get_node(forest, ob1); + dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA); + } } } } @@ -5026,12 +5003,12 @@ static void clothModifier_updateDepgraph( CustomDataMask clothModifier_requiredDataMask(ModifierData *md) { - ClothModifierData *clmd = (ClothModifierData *)md; + ClothModifierData *clmd = (HookModifierData *)md; CustomDataMask dataMask = 0; /* ask for vertexgroups if we need them */ - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) - if (clmd->sim_parms->vgroup_mass > 0) + if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL) + if (clmd->sim_parms.vgroup_mass > 0) dataMask |= (1 << CD_MDEFORMVERT); return dataMask; @@ -5049,154 +5026,9 @@ static void clothModifier_freeData(ModifierData *md) if (clmd) { - - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; + clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; cloth_free_modifier (clmd); - - MEM_freeN(clmd->sim_parms); - MEM_freeN(clmd->coll_parms); - } -} - -/* Collision */ - -static void collisionModifier_initData(ModifierData *md) -{ - CollisionModifierData *collmd = (CollisionModifierData*) md; - - collmd->x = NULL; - collmd->xnew = NULL; - collmd->current_x = NULL; - collmd->current_xnew = NULL; - collmd->current_v = NULL; - collmd->time = -1; - collmd->numverts = 0; - collmd->tree = NULL; -} - -static void collisionModifier_freeData(ModifierData *md) -{ - CollisionModifierData *collmd = (CollisionModifierData*) md; - - if (collmd) - { - if(collmd->tree) - bvh_free(collmd->tree); - if(collmd->x) - MEM_freeN(collmd->x); - if(collmd->xnew) - MEM_freeN(collmd->xnew); - if(collmd->current_x) - MEM_freeN(collmd->current_x); - if(collmd->current_xnew) - MEM_freeN(collmd->current_xnew); - if(collmd->current_v) - MEM_freeN(collmd->current_v); - - collmd->x = NULL; - collmd->xnew = NULL; - collmd->current_x = NULL; - collmd->current_xnew = NULL; - collmd->current_v = NULL; - collmd->time = -1; - collmd->numverts = 0; - collmd->tree = NULL; - } -} - -static int collisionModifier_dependsOnTime(ModifierData *md) -{ - return 1; -} - -static void collisionModifier_deformVerts( - ModifierData *md, Object *ob, DerivedMesh *derivedData, - float (*vertexCos)[3], int numVerts) -{ - CollisionModifierData *collmd = (CollisionModifierData*) md; - DerivedMesh *dm = NULL; - float current_time = 0; - unsigned int numverts = 0, i = 0; - MVert *tempVert = NULL; - - // if possible use/create DerivedMesh - - if(derivedData) dm = CDDM_copy(derivedData); - else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); - - if(!ob->pd) - { - printf("collisionModifier_deformVerts: Should not happen!\n"); - return; - } - - if(dm) - { - CDDM_apply_vert_coords(dm, vertexCos); - CDDM_calc_normals(dm); - - - current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); - - if(current_time > collmd->time) - { - numverts = dm->getNumVerts ( dm ); - - // check if mesh has changed - if(collmd->x && (numverts != collmd->numverts)) - collisionModifier_freeData((ModifierData *)collmd); - - if(collmd->time == -1) // first time - { - collmd->x = dm->dupVertArray(dm); // frame start position - - for ( i = 0; i < numverts; i++ ) - { - // we save global positions - Mat4MulVecfl ( ob->obmat, collmd->x[i].co ); - } - - collmd->xnew = MEM_dupallocN(collmd->x); // frame end position - collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame - collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame - collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame - - collmd->numverts = numverts; - - // TODO: epsilon - // create bounding box hierarchy - collmd->tree = bvh_build_from_mvert(dm->getFaceArray(dm), dm->getNumFaces(dm), collmd->current_x, numverts, ob->pd->pdef_sbift); - } - else if(numverts == collmd->numverts) - { - // put positions to old positions - tempVert = collmd->x; - collmd->x = collmd->xnew; - collmd->xnew = tempVert; - - memcpy(collmd->xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); - - for ( i = 0; i < numverts; i++ ) - { - // we save global positions - Mat4MulVecfl ( ob->obmat, collmd->xnew[i].co ); - } - - memcpy(collmd->current_xnew, dm->getVertArray(dm), numverts*sizeof(MVert)); - memcpy(collmd->current_x, dm->getVertArray(dm), numverts*sizeof(MVert)); - - // recalc static bounding boxes - bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0); - - printf("bvh_update_from_mvert\n"); - } - - collmd->time = current_time; - } } - - if(dm) - dm->release(dm); } /* Boolean */ @@ -7010,10 +6842,10 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->deformVerts = softbodyModifier_deformVerts; mti = INIT_TYPE(Cloth); - mti->type = eModifierTypeType_Nonconstructive; + mti->type = eModifierTypeType_OnlyDeform; mti->initData = clothModifier_initData; - mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_RequiresOriginalData; + mti->flags = eModifierTypeFlag_AcceptsCVs; + // | eModifierTypeFlag_RequiresOriginalData; // | eModifierTypeFlag_SupportsMapping // | eModifierTypeFlag_SupportsEditmode // | eModifierTypeFlag_EnableInEditmode; @@ -7021,19 +6853,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->freeData = clothModifier_freeData; mti->requiredDataMask = clothModifier_requiredDataMask; // mti->copyData = clothModifier_copyData; - // mti->deformVerts = clothModifier_deformVerts; - mti->applyModifier = clothModifier_applyModifier; + mti->deformVerts = clothModifier_deformVerts; mti->updateDepgraph = clothModifier_updateDepgraph; - - mti = INIT_TYPE(Collision); - mti->type = eModifierTypeType_OnlyDeform; - mti->initData = collisionModifier_initData; - mti->flags = eModifierTypeFlag_AcceptsMesh - | eModifierTypeFlag_RequiresOriginalData; - mti->dependsOnTime = collisionModifier_dependsOnTime; - mti->freeData = collisionModifier_freeData; - mti->deformVerts = collisionModifier_deformVerts; - // mti->copyData = collisionModifier_copyData; mti = INIT_TYPE(Boolean); mti->type = eModifierTypeType_Nonconstructive; @@ -7293,11 +7114,11 @@ int modifiers_isSoftbodyEnabled(Object *ob) return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -ClothModifierData *modifiers_isClothEnabled(Object *ob) +ModifierData * modifiers_isClothEnabled(Object *ob) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); - return clmd; + return md; } int modifiers_isParticleEnabled(Object *ob) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d215bdf67cd..37d15b65de5 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2986,12 +2986,14 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) ClothModifierData *clmd = (ClothModifierData*) md; clmd->clothObject = NULL; - + /* clmd->sim_parms= newdataadr(fd, clmd->sim_parms); clmd->coll_parms= newdataadr(fd, clmd->coll_parms); + */ } else if (md->type==eModifierType_Collision) { + /* CollisionModifierData *collmd = (CollisionModifierData*) md; collmd->x = NULL; @@ -3001,6 +3003,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) collmd->time = -1; collmd->numverts = 0; collmd->tree = NULL; + */ } else if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 275e3b18c4c..3326d38c56f 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -827,8 +827,10 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) } else if(md->type==eModifierType_Cloth) { ClothModifierData *clmd = (ClothModifierData*) md; + /* writestruct(wd, DATA, "SimulationSettings", 1, clmd->sim_parms); writestruct(wd, DATA, "CollisionSettings", 1, clmd->coll_parms); + */ } else if (md->type==eModifierType_MeshDeform) { MeshDeformModifierData *mmd = (MeshDeformModifierData*) md; diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 4d8fbf1a6fc..2bbe328d170 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -32,7 +32,64 @@ #ifndef DNA_CLOTH_TYPES_H #define DNA_CLOTH_TYPES_H -typedef struct SimulationSettings { +#include "DNA_listBase.h" + + +/** +* Pin and unpin frames are the frames on which the vertices stop moving. +* They will assume the position they had prior to pinFrame until unpinFrame +* is reached. +*/ +typedef struct ClothVertex +{ + int flags; /* General flags per vertex. */ + float v [3]; /* The velocity of the point. */ + float xconst [3]; /* constrained position */ + float x [3]; /* The current position of this vertex. */ + float xold [3]; /* The previous position of this vertex.*/ + float tx [3]; /* temporary position */ + float txold [3]; /* temporary old position */ + float tv[3]; /* temporary "velocity", mostly used as tv = tx-txold */ + 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 */ +} +ClothVertex; + + +/** +* The definition of a spring. +*/ +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; + + + +/** +* This struct contains all the global data required to run a simulation. +* At the time of this writing, this structure contains data appropriate +* to run a simulation as described in Deformation Constraints in a +* Mass-Spring Model to Describe Rigid Cloth Behavior by Xavier Provot. +* +* I've tried to keep similar, if not exact names for the variables as +* are presented in the paper. Where I've changed the concept slightly, +* as in stepsPerFrame comapred to the time step in the paper, I've used +* variables with different names to minimize confusion. +**/ +typedef struct SimulationSettings +{ short vgroup_mass; /* optional vertexgroup name for assigning weight. */ short pad; float mingoal; /* see SB */ @@ -55,23 +112,56 @@ typedef struct SimulationSettings { float eff_force_scale;/* Scaling of effector forces (see softbody_calc_forces).*/ float eff_wind_scale; /* Scaling of effector wind (see softbody_calc_forces). */ float sim_time_old; + struct LinkNode *cache; float defgoal; - float goalfrict; + int goalfrict; float goalspring; int maxspringlen; /* in percent!; if tearing enabled, a spring will get cut */ int lastframe; /* frame on which simulation stops */ int firstframe; /* frame on which simulation starts */ -} SimulationSettings; + struct Object *ob; +} +SimulationSettings; + -typedef struct CollisionSettings { +typedef struct CollisionSettings +{ float epsilon; /* The radius of a particle in the cloth. */ float self_friction; /* Fiction/damping with self contact. */ float friction; /* Friction/damping applied on contact with other object.*/ short collision_type; /* which collision system is used. */ short loop_count; /* How many iterations for the collision loop. */ + struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */ int flags; /* collision flags defined in BKE_cloth.h */ - float selfepsilon; -} CollisionSettings; + int pad; +} +CollisionSettings; +/** +* This structure describes a cloth object against which the +* simulation can run. +* +* The m and n members of this structure represent the assumed +* rectangular ordered grid for which the original paper is written. +* At some point they need to disappear and we need to determine out +* own connectivity of the mesh based on the actual edges in the mesh. +* +**/ +typedef struct Cloth +{ + struct ClothVertex *verts; /* The vertices that represent this cloth. */ + struct LinkNode *springs; /* The springs connecting the mesh. */ + unsigned int numverts; /* The number of verts == m * n. */ + unsigned int numsprings; /* The count of springs. */ + unsigned int numfaces; + unsigned char old_solver_type; + unsigned char pad2; + short pad3; + void *tree; /* collision tree for this cloth object */ + struct MFace *mfaces; + void *implicit; /* our implicit solver connects to this pointer */ +} +Cloth; + #endif diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 384ac37484d..f8b6f4202a5 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -7,6 +7,8 @@ #define MODSTACK_DEBUG 1 +#include "DNA_cloth_types.h" + /* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! */ typedef enum ModifierType { @@ -347,8 +349,8 @@ typedef struct ClothModifierData { ModifierData modifier; struct Cloth *clothObject; /* The internal data structure for cloth. */ - struct SimulationSettings *sim_parms; /* definition is in DNA_cloth_types.h */ - struct CollisionSettings *coll_parms; /* definition is in DNA_cloth_types.h */ + struct SimulationSettings sim_parms; /* definition is in DNA_cloth_types.h */ + struct CollisionSettings coll_parms; /* definition is in DNA_cloth_types.h */ } ClothModifierData; typedef struct CollisionModifierData { diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index f71f6adb051..662e0df093b 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -48,7 +48,6 @@ #include "BKE_action.h" #include "BKE_cloth.h" -#include "BKE_collisions.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_library.h" @@ -2989,29 +2988,66 @@ void do_effects_panels(unsigned short event) allqueue(REDRAWVIEW3D, 0); break; case B_CLOTH_CLEARCACHEALL: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + CFRA= 1; + update_for_newframe_muted(); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + cloth_clear_cache(ob, clmd, 2); + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); + } + } + break; + case B_CLOTH_CLEARCACHEFRAME: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) + cloth_clear_cache(ob, clmd, MAX2(2.0,G.scene->r.cfra + 1.0)); + allqueue(REDRAWBUTSOBJECT, 0); + } + } + break; + case B_CLOTH_CHANGEPREROLL: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + if(clmd->sim_parms.cache) { CFRA= 1; update_for_newframe_muted(); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - cloth_clear_cache(ob, clmd, 2); allqueue(REDRAWBUTSOBJECT, 0); allqueue(REDRAWVIEW3D, 0); - } + } } - break; + } + break; + case B_CLOTH_DEL_VG: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) + { + clmd->sim_parms.vgroup_mass = 0; + do_object_panels(B_CLOTH_RENEW); + } + allqueue(REDRAWBUTSOBJECT, 0); + } + break; case B_CLOTH_RENEW: + { + ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + if(clmd) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) - { - do_object_panels(B_CLOTH_CLEARCACHEALL); - cloth_free_modifier (clmd); - } + do_object_panels(B_CLOTH_CLEARCACHEALL); + cloth_free_modifier (clmd); } - break; + } + break; default: if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) { ob= OBACT; @@ -4787,9 +4823,9 @@ static void object_panel_cloth(Object *ob) 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"); + 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)) + if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { Cloth *cloth = clmd->clothObject; int defCount; @@ -4798,18 +4834,18 @@ static void object_panel_cloth(Object *ob) 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"); + // 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)"); + 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, "Steps per Frame:", 10,150,150,20, &clmd->sim_parms.stepsPerFrame, 1.0, 100.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"); + 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(); @@ -4818,15 +4854,15 @@ static void object_panel_cloth(Object *ob) 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"); + 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) + 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) { @@ -4841,17 +4877,17 @@ static void object_panel_cloth(Object *ob) defCount = BLI_countlist (&ob->defbase); if (defCount == 0) { - clmd->sim_parms->vgroup_mass = 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"); + 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) + if(clmd->sim_parms.vgroup_mass) { - bDeformGroup *defGroup = BLI_findlink(&ob->defbase, clmd->sim_parms->vgroup_mass-1); + 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 @@ -4861,31 +4897,31 @@ static void object_panel_cloth(Object *ob) } 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"); + 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"); + 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"); + 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"); + 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) + 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"); - } + 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); */ @@ -4904,7 +4940,7 @@ static void object_panel_cloth_II(Object *ob) clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { - if (!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) + if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { Cloth *cloth = clmd->clothObject; char str[128]; @@ -4915,18 +4951,18 @@ static void object_panel_cloth_II(Object *ob) 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) + 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); + 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); + /* 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); + 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, ""); @@ -4934,15 +4970,15 @@ static void object_panel_cloth_II(Object *ob) 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"); + 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 + 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"); + } + 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); } } @@ -4952,32 +4988,41 @@ static void object_panel_cloth_II(Object *ob) static void object_panel_cloth_III(Object *ob) { uiBlock *block; + static int val; + uiBut *but; 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) + { + if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ)) { - // 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.49f, 0, "Minimum distance between two selfcollision points"); + Cloth *cloth = clmd->clothObject; + char str[128]; + + 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,70,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,30,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,30,150,20, NULL, 0.0, 0, 0, 0, ""); + } + else + uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, ""); + uiBlockEndAlign(block); } - else - uiDefBut(block, LABEL, 0, "",140,10,170,20, NULL, 0.0, 0, 0, 0, ""); - uiBlockEndAlign(block); } + // uiBlockEndAlign(block); } + void object_panels() { Object *ob; diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 111f0789ee9..61e4c6d5660 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -2454,112 +2454,6 @@ void draw_slices ( float m[][4] ) } } - -void draw_fl(ClothModifierData *clmd) -{ - int i; - float m[4][4]; - Cloth *cloth = clmd->clothObject; - fc *m_fc = NULL; - - if(!cloth) - return; - - m_fc = cloth->m_fc; - - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - // gluLookAt(0, 0, -_dist, 0, 0, 0, 0, 1, 0); - - // build_rotmatrix(m, _quat); - - glMultMatrixf(&m[0][0]); - - // ---------------------------------------- - // from ligth constructor - m_fc->_light_dir[0] = -1.0f; - m_fc->_light_dir[1] = 0.5f; - m_fc->_light_dir[2] = 0.0f; - - gen_ray_templ(m_fc->_ray_templ, m_fc->_light_dir, 30 + 2); - - cast_light(m_fc->_texture_data, m_fc->_ray_templ, m_fc->_light_dir, 30+2); - - glActiveTextureARB(GL_TEXTURE0_ARB); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 30+2, 30+2, 30+2, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_fc->_texture_data); - // ---------------------------------------- - - draw_slices(m); -/* - if (_dispstring != NULL) { - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(_ortho_m); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glDisable(GL_TEXTURE_3D); - glDisable(GL_FRAGMENT_PROGRAM_ARB); - glColor4f(1.0, 1.0, 1.0, 1.0); - glRasterPos2i(-_sx/2 + 10, _sy/2 - 15); - - print_string(_dispstring); - - glMatrixMode(GL_PROJECTION); - glLoadMatrixd(_persp_m); - glMatrixMode(GL_MODELVIEW); - } -*/ -} - -void fc_load_frame(ClothModifierData *clmd) -{ - float* tmp = (float*) MEM_callocN(30*30*30*sizeof(float), "fc_tmp"); - float tmin=9999999, tmax=-99999999; - Cloth *cloth = clmd->clothObject; - fc *m_fc = NULL; - int i = 0; - - if(!cloth) - return; - - m_fc = cloth->m_fc; - - if (++m_fc->_cur_frame == m_fc->_nframes) { - fseek(m_fc->_fp, 12, SEEK_SET); - m_fc->_cur_frame = 0; - } - - fread(tmp, sizeof(float), 30*30*30, m_fc->_fp); - - for (i=0; i<30*30*30; i++) - { - m_fc->_texture_data[(i<<2)+1] = (unsigned char) (tmp[i]*255.0f); - } - - fread(tmp, sizeof(float), 30*30*30, m_fc->_fp); - - for (i=0; i<30*30*30; i++) - { - m_fc->_texture_data[(i<<2)] = (unsigned char) (tmp[i]*255.0f); - if (tmp[i]<tmin) - tmin = tmp[i]; - if (tmp[i]>tmax) - tmax = tmp[i]; - m_fc->_texture_data[(i<<2)+2] = 0; - m_fc->_texture_data[(i<<2)+3] = 255; - } - - MEM_freeN(tmp); - - // cast_light(_N); DG NOT NEEDED - - glActiveTextureARB(GL_TEXTURE0_ARB); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 30, 30, 30, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_fc->_texture_data); -} - static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm) { diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c index 615a9566b97..2e4ecd95709 100644 --- a/source/blender/src/vpaint.c +++ b/source/blender/src/vpaint.c @@ -51,6 +51,7 @@ #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_brush_types.h" +#include "DNA_cloth_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -747,7 +748,7 @@ static int sample_backbuf_area(VPaint *vp, int *indexar, int totface, int x, int struct ImBuf *ibuf; int x1, y1, x2, y2, a, tot=0, index; - if(totface>=MAXINDEX) return 0; + if(totface+4>=MAXINDEX) return 0; if(size>64.0) size= 64.0; @@ -777,7 +778,7 @@ static int sample_backbuf_area(VPaint *vp, int *indexar, int totface, int x, int size= (y2-y1)*(x2-x1); if(size<=0) return 0; - memset(indexar, 0, sizeof(int)*totface+2); /* plus 2! first element is total */ + memset(indexar, 0, sizeof(int)*totface+4); /* plus 2! first element is total, +2 was giving valgrind errors, +4 seems ok */ while(size--) { @@ -1350,7 +1351,7 @@ void weight_paint(void) // same goes for cloth if(modifiers_isClothEnabled(ob)) { - cloth_free_modifier(modifiers_isClothEnabled(ob)); + cloth_free_modifier((ClothModifierData *)modifiers_isClothEnabled(ob)); } BIF_undo_push("Weight Paint"); |