svn merge -r 12347:12382 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorDaniel Genrich <daniel.genrich@gmx.net>
Wed, 24 Oct 2007 17:20:53 +0000 (17:20 +0000)
committerDaniel Genrich <daniel.genrich@gmx.net>
Wed, 24 Oct 2007 17:20:53 +0000 (17:20 +0000)
36 files changed:
SConstruct
extern/SConscript
extern/bullet2/src/Bullet-C-Api.h [new file with mode: 0644]
extern/bullet2/src/BulletDynamics/CMakeLists.txt
extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp [new file with mode: 0644]
extern/bullet2/src/SConscript
intern/elbeem/SConscript
intern/elbeem/intern/paraloop.h [new file with mode: 0644]
intern/elbeem/intern/paraloopend.h [new file with mode: 0644]
intern/elbeem/intern/paraloopstart.h [new file with mode: 0644]
source/Makefile
source/blender/blenkernel/BKE_cloth.h [new file with mode: 0644]
source/blender/blenkernel/BKE_collisions.h [new file with mode: 0644]
source/blender/blenkernel/BKE_modifier.h
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/Makefile
source/blender/blenkernel/intern/cloth.c [new file with mode: 0644]
source/blender/blenkernel/intern/collision.c [new file with mode: 0644]
source/blender/blenkernel/intern/implicit.c [new file with mode: 0644]
source/blender/blenkernel/intern/kdop.c [new file with mode: 0644]
source/blender/blenkernel/intern/modifier.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/butspace.h
source/blender/makesdna/DNA_cloth_types.h [new file with mode: 0644]
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/intern/makesdna.c
source/blender/src/buttons_editing.c
source/blender/src/buttons_object.c
source/blender/src/editmesh.c
source/blender/src/editobject.c
source/blender/src/transform_conversions.c
source/blender/src/transform_generics.c
source/blender/src/vpaint.c
tools/btools.py

index 2cacb91d10342114d1b9ef5d2baf5fbd853b863f..7fad247ec07cde6300ac05a072ea224a2177d323 100644 (file)
@@ -176,6 +176,18 @@ if env['BF_NO_ELBEEM'] == 1:
     env['CXXFLAGS'].append('-DDISABLE_ELBEEM')
     env['CCFLAGS'].append('-DDISABLE_ELBEEM')
 
+if env['WITH_BF_OPENMP'] == 1:
+       if env['OURPLATFORM']=='win32-vc':
+               env.Append(LINKFLAGS=['/openmp'])
+               env['CCFLAGS'].append('/openmp')
+               env['CPPFLAGS'].append('/openmp')
+               env['CXXFLAGS'].append('/openmp')
+       else:
+               env.Append(LINKFLAGS=['-lgomp'])
+               env['CCFLAGS'].append('-fopenmp')
+               env['CPPFLAGS'].append('-fopenmp')
+               env['CXXFLAGS'].append('-fopenmp')
+
 #check for additional debug libnames
 
 if env.has_key('BF_DEBUG_LIBS'):
index 924b7f54507e9ba7cc846ff7d056d9bb24634f9e..766e2a5b188ad0c5af2f8685f9678481e98de468 100644 (file)
@@ -5,8 +5,9 @@ Import('env')
 if env['WITH_BF_GAMEENGINE']:
     SConscript(['qhull/SConscript',
             'solid/SConscript'])
-    if env['WITH_BF_BULLET']:
-        SConscript(['bullet2/src/SConscript'])
+
+if env['WITH_BF_BULLET']:
+    SConscript(['bullet2/src/SConscript'])
 
 if env['WITH_BF_INTERNATIONAL']:
     SConscript(['bFTGL/SConscript'])
diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h
new file mode 100644 (file)
index 0000000..ccb0c45
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef Bullet_C_API_H
+#define Bullet_C_API_H
+
+#ifdef __cplusplus
+extern "C"  {
+#endif // __cplusplus
+
+double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif
+
index 79e07b7f77bca7ab6664bcc26f6e4a583cc813ae..4cda87a146a8e160d0965d5070b139a88dc8e910 100644 (file)
@@ -14,6 +14,7 @@ ADD_LIBRARY(LibBulletDynamics
        Dynamics/btDiscreteDynamicsWorld.cpp
        Dynamics/btSimpleDynamicsWorld.cpp
        Dynamics/btRigidBody.cpp
+       Dynamics/Bullet-C-Api.cpp
        Vehicle/btRaycastVehicle.cpp
        Vehicle/btWheelInfo.cpp
 )
diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-Api.cpp
new file mode 100644 (file)
index 0000000..4051d3f
--- /dev/null
@@ -0,0 +1,91 @@
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btScalar.h"       
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btTransform.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPointCollector.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h"
+#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "LinearMath/btStackAlloc.h"
+
+
+extern "C"
+double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3])
+{
+       btTriangleShape trishapeA(btVector3(p1[0], p1[1], p1[2]), btVector3(p2[0], p2[1], p2[2]), btVector3(p3[0], p3[1], p3[2]));
+       trishapeA.setMargin(0.000001f);
+       
+       btTriangleShape trishapeB(btVector3(q1[0], q1[1], q1[2]), btVector3(q2[0], q2[1], q2[2]), btVector3(q3[0], q3[1], q3[2]));
+       trishapeB.setMargin(0.000001f);
+       
+       // btVoronoiSimplexSolver sGjkSimplexSolver;
+       // btGjkEpaPenetrationDepthSolver penSolverPtr; 
+       
+       static btSimplexSolverInterface sGjkSimplexSolver;
+       sGjkSimplexSolver.reset();
+       
+       static btGjkEpaPenetrationDepthSolver Solver0;
+       static btMinkowskiPenetrationDepthSolver Solver1;
+               
+       btConvexPenetrationDepthSolver* Solver = NULL;
+       
+       Solver = &Solver1;      
+               
+       btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,Solver);
+       
+       convexConvex.m_catchDegeneracies = 1;
+       
+       // btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,0);
+       
+       btPointCollector gjkOutput;
+       btGjkPairDetector::ClosestPointInput input;
+       
+       btStackAlloc gStackAlloc(1024*1024*2);
+       input.m_stackAlloc = &gStackAlloc;
+       
+       btTransform tr;
+       tr.setIdentity();
+       
+       input.m_transformA = tr;
+       input.m_transformB = tr;
+       
+       convexConvex.getClosestPoints(input, gjkOutput, 0);
+       
+       
+       if (gjkOutput.m_hasResult)
+       {
+               
+               pb[0] = pa[0] = gjkOutput.m_pointInWorld[0];
+               pb[1] = pa[1] = gjkOutput.m_pointInWorld[1];
+               pb[2] = pa[2] = gjkOutput.m_pointInWorld[2];
+
+               pb[0]+= gjkOutput.m_normalOnBInWorld[0] * gjkOutput.m_distance;
+               pb[1]+= gjkOutput.m_normalOnBInWorld[1] * gjkOutput.m_distance;
+               pb[2]+= gjkOutput.m_normalOnBInWorld[2] * gjkOutput.m_distance;
+               
+               normal[0] = gjkOutput.m_normalOnBInWorld[0];
+               normal[1] = gjkOutput.m_normalOnBInWorld[1];
+               normal[2] = gjkOutput.m_normalOnBInWorld[2];
+
+               return gjkOutput.m_distance;
+       }
+       return -1.0f;   
+}
+
index 6280c49066d1987777df352d5ae21d1686ba5980..127752777c8f9803f83c19caa6f78eaef3525611 100644 (file)
@@ -33,6 +33,7 @@ bulletdyn_src = ["BulletDynamics/ConstraintSolver/btContactConstraint.cpp",
                  "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp",
                  "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp",
                  "BulletDynamics/Dynamics/btRigidBody.cpp",
+                "BulletDynamics/Dynamics/Bullet-C-Api.cpp",
                  "BulletDynamics/Vehicle/btRaycastVehicle.cpp",
                  "BulletDynamics/Vehicle/btWheelInfo.cpp"]
 collision_src = ["BulletCollision/BroadphaseCollision/btAxisSweep3.cpp",
index bb6637ba32d1109cf2cd431cb6edbe3eba1b5a85..bdcb050798731480fef9681b3f77f408d57303d6 100644 (file)
@@ -5,7 +5,11 @@ Import('env')
 
 sources = env.Glob('intern/*.cpp')
 
-defs = 'NOGUI ELBEEM_BLENDER=1'
+defs = ' NOGUI ELBEEM_BLENDER=1'
+
+if env['WITH_BF_OPENMP'] == 1:
+    defs += ' PARALLEL'
+
 if env['OURPLATFORM']=='win32-vc':
     defs += ' USE_MSVC6FIXES'
 incs = env['BF_PNG_INC'] + ' ' + env['BF_ZLIB_INC'] + ' ' +env['BF_SDL_INC']
diff --git a/intern/elbeem/intern/paraloop.h b/intern/elbeem/intern/paraloop.h
new file mode 100644 (file)
index 0000000..fba0ae4
--- /dev/null
@@ -0,0 +1,50 @@
+
+#define PERFORM_USQRMAXCHECK \
+_Pragma("omp critical") {\
+USQRMAXCHECK(usqr,ux,uy,uz, mMaxVlen, mMxvx,mMxvy,mMxvz); \
+} \
+
+
+#define LIST_EMPTY(x) \
+_Pragma("omp critical") {\
+mListEmpty.push_back( x ); }
+
+#define LIST_FULL(x) \
+_Pragma("omp critical") {\
+mListFull.push_back( x ); }
+
+#define FSGR_ADDPART(x)  \
+_Pragma("omp critical") { \
+mpParticles->addFullParticle( x ); } \
+
+
+#define MAX_THREADS 2
+
+#define  GRID_REGION_START()  \
+{ /* main_region */ \
+       int kstart=getForZMinBnd(), kend=getForZMaxBnd(mMaxRefine); \
+       if(gridLoopBound>0){ kstart=getForZMin1(), kend=getForZMax1(mMaxRefine); } \
+       int kdir = 1; \
+       const int id=omp_get_thread_num(); \
+       int jstart = (id*((mLevel[mMaxRefine].lSizey-gridLoopBound) / MAX_THREADS))+gridLoopBound; \
+       int jend   = (id+1)*((mLevel[mMaxRefine].lSizey-gridLoopBound)/ MAX_THREADS); \
+       if(id+1 == MAX_THREADS) \
+       { \
+       jend = mLevel[mMaxRefine].lSizey-gridLoopBound; \
+       } \
+       LbmFloat *ccel = NULL, *tcel = NULL; \
+       CellFlagType *pFlagSrc=NULL, *pFlagDst=NULL; \
+       if(mLevel[mMaxRefine].setCurr==1) { \
+       kdir = -1; \
+       int temp = kend; \
+       kend = kstart-1; \
+       kstart = temp-1; \
+       temp = id; /* dummy remove warning */ \
+} \
+
+// if(jstart<1) jstart = 1; 
+
+#define unused_GRID_REGION_END() \
+} /* main_region */  \
+       // end unusedGRID_REGION_END
+
diff --git a/intern/elbeem/intern/paraloopend.h b/intern/elbeem/intern/paraloopend.h
new file mode 100644 (file)
index 0000000..889e293
--- /dev/null
@@ -0,0 +1,13 @@
+// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+} /* i */ 
+       int i=0; 
+       ADVANCE_POINTERS(2*gridLoopBound); 
+} /* j */ 
+#pragma omp barrier 
+       /* COMPRESSGRIDS!=1 */ 
+       /* int i=0;  */ 
+       /* ADVANCE_POINTERS(mLevel[lev].lSizex*2);  */ 
+} /* all cell loop k,j,i */ 
+       if(doReduce) { } /* dummy remove warning */ 
+} /* main_region */ 
+
diff --git a/intern/elbeem/intern/paraloopstart.h b/intern/elbeem/intern/paraloopstart.h
new file mode 100644 (file)
index 0000000..e594081
--- /dev/null
@@ -0,0 +1,3 @@
+
+#pragma omp parallel num_threads(MAX_THREADS) \
+reduction(+: calcCurrentMass, calcCurrentVolume, calcCellsFilled, calcCellsEmptied, calcNumUsedCells) 
index 5161f6b73c517b7ee8bd34411d391c33f6a01093..e68aca215a1a2ee8dc7f741eb33adcdf2628bffd 100644 (file)
@@ -149,9 +149,11 @@ ifneq ($(NAN_NO_KETSJI),true)
     COMLIB += $(OCGDIR)/gameengine/ketsji/KXNetwork/$(DEBUG_DIR)libKXNetwork.a
     COMLIB += $(OCGDIR)/gameengine/Network/$(DEBUG_DIR)libNetwork.a
     COMLIB += $(OCGDIR)/gameengine/Network/LoopBackNetwork/$(DEBUG_DIR)libLoopBackNetwork.a
-    COMLIB += $(NAN_BULLET2)/lib/libbullet2.a
 endif
 
+# Required by cloth, not gameengine only anymore
+COMLIB += $(NAN_BULLET2)/lib/$(DEBUG_DIR)libbullet2.a
+
 COMLIB += $(NAN_GUARDEDALLOC)/lib/libguardedalloc.a
 COMLIB += $(NAN_MEMUTIL)/lib/libmemutil.a
 COMLIB += $(NAN_BMFONT)/lib/$(DEBUG_DIR)libbmfont.a
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
new file mode 100644 (file)
index 0000000..1985132
--- /dev/null
@@ -0,0 +1,222 @@
+/**
+ * BKE_cloth.h
+ *
+ * $Id: BKE_cloth.h,v 1.1 2007/08/01 02:07:27 daniel Exp $
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_CLOTH_H
+#define BKE_CLOTH_H
+
+#include "BLI_linklist.h"
+#include "BKE_DerivedMesh.h"
+#include "DNA_customdata_types.h"
+#include "BKE_customdata.h"
+#include "DNA_meshdata_types.h"
+
+struct Object;
+struct Cloth;
+struct MFace;
+struct DerivedMesh;
+
+// this is needed for inlining behaviour
+#ifndef _WIN32
+#define LINUX
+#define DO_INLINE inline
+#else
+#define DO_INLINE
+#endif
+
+#define CLOTH_MAX_THREAD 2
+
+
+/* goal defines */
+#define SOFTGOALSNAP  0.999f
+
+/* This is approximately the smallest number that can be
+* represented by a float, given its precision. */
+#define ALMOST_ZERO            0.000001
+
+// some macro enhancements for vector treatment
+#define VECADDADD(v1,v2,v3)    {*(v1)+= *(v2) + *(v3); *(v1+1)+= *(v2+1) + *(v3+1); *(v1+2)+= *(v2+2) + *(v3+2);}
+#define VECSUBADD(v1,v2,v3)    {*(v1)-= *(v2) + *(v3); *(v1+1)-= *(v2+1) + *(v3+1); *(v1+2)-= *(v2+2) + *(v3+2);}
+#define VECADDSUB(v1,v2,v3)    {*(v1)+= *(v2) - *(v3); *(v1+1)+= *(v2+1) - *(v3+1); *(v1+2)+= *(v2+2) - *(v3+2);}
+#define VECSUBADDSS(v1,v2,aS,v3,bS)    {*(v1)-= *(v2)*aS + *(v3)*bS; *(v1+1)-= *(v2+1)*aS + *(v3+1)*bS; *(v1+2)-= *(v2+2)*aS + *(v3+2)*bS;}
+#define VECADDSUBSS(v1,v2,aS,v3,bS)    {*(v1)+= *(v2)*aS - *(v3)*bS; *(v1+1)+= *(v2+1)*aS - *(v3+1)*bS; *(v1+2)+= *(v2+2)*aS - *(v3+2)*bS;}
+#define VECADDSS(v1,v2,aS,v3,bS)       {*(v1)= *(v2)*aS + *(v3)*bS; *(v1+1)= *(v2+1)*aS + *(v3+1)*bS; *(v1+2)= *(v2+2)*aS + *(v3+2)*bS;}
+#define VECADDS(v1,v2,v3,bS)   {*(v1)= *(v2) + *(v3)*bS; *(v1+1)= *(v2+1) + *(v3+1)*bS; *(v1+2)= *(v2+2) + *(v3+2)*bS;}
+#define VECSUBMUL(v1,v2,aS)    {*(v1)-= *(v2) * aS; *(v1+1)-= *(v2+1) * aS; *(v1+2)-= *(v2+2) * aS;}
+#define VECSUBS(v1,v2,v3,bS)   {*(v1)= *(v2) - *(v3)*bS; *(v1+1)= *(v2+1) - *(v3+1)*bS; *(v1+2)= *(v2+2) - *(v3+2)*bS;}
+#define VECSUBSB(v1,v2, v3,bS)         {*(v1)= (*(v2)- *(v3))*bS; *(v1+1)= (*(v2+1) - *(v3+1))*bS; *(v1+2)= (*(v2+2) - *(v3+2))*bS;}
+#define VECMULS(v1,aS)         {*(v1)*= aS; *(v1+1)*= aS; *(v1+2)*= *aS;}
+#define VECADDMUL(v1,v2,aS)    {*(v1)+= *(v2) * aS; *(v1+1)+= *(v2+1) * aS; *(v1+2)+= *(v2+2) * aS;}
+
+/* SIMULATION FLAGS: goal flags,.. */
+/* These are the bits used in SimSettings.flags. */
+typedef enum
+{
+    CLOTH_SIMSETTINGS_FLAG_RESET = ( 1 << 1 ),         // The CM object requires a reinitializaiton.
+    CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ),       // object is only collision object, no cloth simulation is done
+    CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ),          // we have goals enabled
+    CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ), // true if tearing is enabled
+    CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), // true if tearing is enabled
+} CLOTH_SIMSETTINGS_FLAGS;
+
+/* SPRING FLAGS */
+typedef enum
+{
+    CLOTH_COLLISIONSETTINGS_FLAG_ENABLED = ( 1 << 1 ),
+} CLOTH_COLLISIONSETTINGS_FLAGS;
+
+/* Spring types as defined in the paper.*/
+typedef enum
+{
+    CLOTH_SPRING_TYPE_STRUCTURAL = 0,
+    CLOTH_SPRING_TYPE_SHEAR,
+    CLOTH_SPRING_TYPE_BENDING,
+} CLOTH_SPRING_TYPES;
+
+/* SPRING FLAGS */
+typedef enum
+{
+    CLOTH_SPRING_FLAG_DEACTIVATE = ( 1 << 1 ),
+    CLOTH_SPRING_FLAG_NEEDED = ( 1 << 2 ), // springs has values to be applied
+} CLOTH_SPRINGS_FLAGS;
+
+/* Bits to or into the ClothVertex.flags. */
+#define CVERT_FLAG_PINNED      1
+#define CVERT_FLAG_COLLISION   2
+
+
+// needed for buttons_object.c
+void cloth_cache_free ( ClothModifierData *clmd, float time );
+void cloth_free_modifier ( ClothModifierData *clmd );
+
+// needed for cloth.c
+void implicit_set_positions ( ClothModifierData *clmd );
+
+// from cloth.c, needed for modifier.c
+DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm);
+
+////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////
+// cloth.c
+////////////////////////////////////////////////
+void cloth_free_modifier ( ClothModifierData *clmd );
+void cloth_init ( 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 ) ( ClothModifierData *clmd, int step );
+// typedef void ( *CM_COLLISION_OBJ ) ( ClothModifierData *clmd, int step, CM_COLLISION_RESPONSE collision_response );
+
+
+/* This enum provides the IDs for our solvers. */
+// only one available in the moment
+typedef enum {
+    CM_IMPLICIT = 0,
+} CM_SOLVER_ID;
+
+
+/* This structure defines how to call the solver.
+*/
+typedef struct
+{
+       char            *name;
+       CM_SOLVER_ID    id;
+       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 ( 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
+       unsigned int face2; // object face
+       double distance; // magnitude of vector
+       float normal[3];
+       float vector[3]; // unnormalized collision vector: p2-p1
+       float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
+       int lastsign; // indicates if the distance sign has changed, unused itm
+       float time; // collision time, from 0 up to 1
+       unsigned int ap1, ap2, ap3, bp1, bp2, bp3, bp4;
+       unsigned int pointsb[4];
+}
+CollPair;
+*/
+
+/* used for collisions in collision.c */
+typedef struct EdgeCollPair
+{
+       unsigned int p11, p12, p21, p22;
+       float normal[3];
+       float vector[3];
+       float time;
+       int lastsign;
+       float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
+}
+EdgeCollPair;
+
+/* used for collisions in collision.c */
+typedef struct FaceCollPair
+{
+       unsigned int p11, p12, p13, p21;
+       float normal[3];
+       float vector[3];
+       float time;
+       int lastsign;
+       float pa[3], pb[3]; // collision point p1 on face1, p2 on face2
+}
+FaceCollPair;
+
+#endif
+
diff --git a/source/blender/blenkernel/BKE_collisions.h b/source/blender/blenkernel/BKE_collisions.h
new file mode 100644 (file)
index 0000000..0a79bb4
--- /dev/null
@@ -0,0 +1,112 @@
+/**
+ * BKE_cloth.h
+ *
+ * $Id: BKE_cloth.h,v 1.1 2007/08/01 02:07:27 daniel Exp $
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+#ifndef BKE_COLLISIONS_H
+#define BKE_COLLISIONS_H
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+/* types */
+#include "BLI_linklist.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_object.h"
+#include "BKE_DerivedMesh.h"
+
+// used in kdop.c and collision.c
+typedef struct CollisionTree
+{
+       struct CollisionTree *nodes[4]; // 4 children --> quad-tree
+       struct CollisionTree *parent;
+       struct CollisionTree *nextLeaf;
+       struct CollisionTree *prevLeaf;
+       float   bv[26]; // Bounding volume of all nodes / we have 7 axes on a 14-DOP
+       int point_index[4]; // supports up to 4 points in a leaf
+       int     count_nodes; // how many nodes are used
+       int     traversed;  // how many nodes already traversed until this level?
+       int     isleaf;
+}
+CollisionTree;
+
+typedef struct CollisionTree TreeNode;
+
+typedef struct BVH
+{
+       unsigned int    numfaces;
+       unsigned int    numverts;
+       MVert           *xnew; // position of verts at time n 
+       MVert           *x; // position of verts at time n-1
+       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;
+
+/* used for collisions in kdop.c and also collision.c*/
+typedef struct CollisionPair
+{
+       int point_indexA[4], point_indexB[4];
+}
+CollisionPair;
+
+
+/////////////////////////////////////////////////
+// forward declarations
+/////////////////////////////////////////////////
+
+// builds bounding volume hierarchy
+BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon);
+
+// frees the same
+void bvh_free ( BVH *bvh );
+
+// checks two bounding volume hierarchies for potential collisions and returns some list with those
+int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision_list);
+
+// update bounding volumes, needs updated positions in bvh->x
+void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving);
+
+LinkNode *BLI_linklist_append_fast (LinkNode **listp, void *ptr);
+
+// move Collision modifier object inter-frame with step = [0,1]
+// defined in collisions.c
+void collision_move_object(CollisionModifierData *collmd, float step);
+
+/////////////////////////////////////////////////
+
+#endif
+
index 297443b883d57b91f24c74eaaece97826d93aec7..644c3dd32f40db36ceb8c8e4eb56a822007ea8ad 100644 (file)
@@ -277,6 +277,7 @@ int           modifiers_getCageIndex(struct Object *ob,
                                      int *lastPossibleCageIndex_r);
 
 int           modifiers_isSoftbodyEnabled(struct Object *ob);
+struct ClothModifierData *modifiers_isClothEnabled(Object *ob);
 struct Object *modifiers_isDeformedByArmature(struct Object *ob);
 struct Object *modifiers_isDeformedByLattice(struct Object *ob);
 int           modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
index 9ecc76046c75e04f62802b20217a35f061383a1b..c83e9f7fbe13574d8c0bbad59740b84b397bc7ec 100644 (file)
@@ -7,6 +7,7 @@ incs = '. #/intern/guardedalloc ../include ../blenlib ../makesdna'
 incs += ' ../python ../render/extern/include #/intern/decimation/extern'
 incs += ' ../imbuf ../avi #/intern/elbeem/extern ../nodes'
 incs += ' #/intern/iksolver/extern ../blenloader ../quicktime'
+incs += ' #/extern/bullet2/src '
 incs += ' #/intern/bmfont'
 
 incs += ' ' + env['BF_OPENGL_INC']
index 89b91ed2a8f6ca1bb0d2b3d75032523b5382a6d6..b3bc6c72996fb990805df891369f1c18964ed68c 100644 (file)
@@ -79,6 +79,9 @@ CPPFLAGS += -I../../nodes
 # path to our own external headerfiles
 CPPFLAGS += -I..
 
+# path to bullet2, for cloth
+CPPFLAGS += -I../../../../extern/bullet2/src
+
 ifeq ($(WITH_FREETYPE2), true)
     CPPFLAGS += -DWITH_FREETYPE2
     CPPFLAGS += -I$(NAN_FREETYPE)/include
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
new file mode 100644 (file)
index 0000000..5ea9137
--- /dev/null
@@ -0,0 +1,1242 @@
+/*  cloth.c
+*
+*
+* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version. The Blender
+* Foundation also sells licenses for use in proprietary software under
+* the Blender License.  See http://www.blender.org/BL/ for information
+* about this.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+* The Original Code is Copyright (C) Blender Foundation
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): none yet.
+*
+* ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+/* types */
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_cloth_types.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_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"
+#include "BLI_edgehash.h"
+#include "BLI_linklist.h"
+
+#include "BKE_curve.h"
+#include "BKE_deform.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_cloth.h"
+#include "BKE_collisions.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"
+#include "BSE_headerbuttons.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "mydevice.h"
+
+#ifdef _WIN32
+void tstart ( void )
+{}
+void tend ( void )
+{
+}
+double tval()
+{
+       return 0;
+}
+#else
+#include <sys/time.h>
+static struct timeval _tstart, _tend;
+static struct timezone tz;
+void tstart ( void )
+{
+       gettimeofday ( &_tstart, &tz );
+}
+void tend ( void )
+{
+       gettimeofday ( &_tend,&tz );
+}
+double tval()
+{
+       double t1, t2;
+       t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 );
+       t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 );
+       return t2-t1;
+}
+#endif
+
+/* Our available solvers. */
+// 255 is the magic reserved number, so NEVER try to put 255 solvers in here!
+// 254 = MAX!
+static CM_SOLVER_DEF   solvers [] =
+    {
+        { "Implicit", CM_IMPLICIT, implicit_init, implicit_solver, implicit_free },
+        // { "Implicit C++", CM_IMPLICITCPP, implicitcpp_init, implicitcpp_solver, implicitcpp_free },
+    };
+
+/* ********** cloth engine ******* */
+/* Prototypes for internal functions.
+*/
+static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
+static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
+static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm );
+int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm );
+static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm, short vgroup );
+
+
+/******************************************************************************
+*
+* External interface called by modifier.c clothModifier functions.
+*
+******************************************************************************/
+/**
+* cloth_init -  creates a new cloth simulation.
+*
+* 1. create object
+* 2. fill object with standard values or with the GUI settings if given
+*/
+void cloth_init ( ClothModifierData *clmd )
+{
+       /* Initialize our new data structure to reasonable values. */
+       clmd->sim_parms.gravity [0] = 0.0;
+       clmd->sim_parms.gravity [1] = 0.0;
+       clmd->sim_parms.gravity [2] = -9.81;
+       clmd->sim_parms.structural = 100.0;
+       clmd->sim_parms.shear = 100.0;
+       clmd->sim_parms.bending = 1.0;
+       clmd->sim_parms.Cdis = 5.0;
+       clmd->sim_parms.Cvi = 1.0;
+       clmd->sim_parms.mass = 1.0f;
+       clmd->sim_parms.stepsPerFrame = 5;
+       clmd->sim_parms.sim_time = 1.0;
+       clmd->sim_parms.flags = CLOTH_SIMSETTINGS_FLAG_RESET;
+       clmd->sim_parms.solver_type = 0;
+       clmd->sim_parms.preroll = 0;
+       clmd->sim_parms.maxspringlen = 10;
+       clmd->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;
+
+       // also from softbodies
+       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 *result = NULL;
+       int i;
+       int numverts = dm->getNumVerts ( dm );
+       int numedges = dm->getNumEdges ( dm );
+       int numfaces = dm->getNumFaces ( dm );
+
+       MVert *mvert = CDDM_get_verts ( dm );
+       MEdge *medge = CDDM_get_edges ( dm );
+       MFace *mface = CDDM_get_faces ( dm );
+
+       MVert *mvert2;
+       MFace *mface2;
+       unsigned int numtris=0;
+       unsigned int numquads=0;
+       int a = 0;
+       int random = 0;
+       int firsttime = 0;
+       float vec1[3], vec2[3], vec3[3], vec4[3], vec5[3];
+       float mag1=0, mag2=0;
+
+       for ( i = 0; i < numfaces; i++ )
+       {
+               if ( mface[i].v4 )
+                       numquads++;
+               else
+                       numtris++;
+       }
+
+       result = CDDM_from_template ( dm, numverts, 0, numtris + 2*numquads );
+
+       if ( !result )
+               return NULL;
+
+       // do verts
+       mvert2 = CDDM_get_verts ( result );
+       for ( a=0; a<numverts; a++ )
+       {
+               MVert *inMV;
+               MVert *mv = &mvert2[a];
+
+               inMV = &mvert[a];
+
+               DM_copy_vert_data ( dm, result, a, a, 1 );
+               *mv = *inMV;
+       }
+
+
+       // do faces
+       mface2 = CDDM_get_faces ( result );
+       for ( a=0, i=0; a<numfaces; a++ )
+       {
+               MFace *mf = &mface2[i];
+               MFace *inMF;
+               inMF = &mface[a];
+
+               /*
+               DM_copy_face_data(dm, result, a, i, 1);
+
+               *mf = *inMF;
+               */
+
+               if ( mface[a].v4 && random==1 )
+               {
+                       mf->v1 = mface[a].v2;
+                       mf->v2 = mface[a].v3;
+                       mf->v3 = mface[a].v4;
+               }
+               else
+               {
+                       mf->v1 = mface[a].v1;
+                       mf->v2 = mface[a].v2;
+                       mf->v3 = mface[a].v3;
+               }
+
+               mf->v4 = 0;
+               mf->flag |= ME_SMOOTH;
+
+               test_index_face ( mf, NULL, 0, 3 );
+
+               if ( mface[a].v4 )
+               {
+                       MFace *mf2;
+
+                       i++;
+
+                       mf2 = &mface2[i];
+                       /*
+                       DM_copy_face_data(dm, result, a, i, 1);
+
+                       *mf2 = *inMF;
+                       */
+
+                       if ( random==1 )
+                       {
+                               mf2->v1 = mface[a].v1;
+                               mf2->v2 = mface[a].v2;
+                               mf2->v3 = mface[a].v4;
+                       }
+                       else
+                       {
+                               mf2->v1 = mface[a].v4;
+                               mf2->v2 = mface[a].v1;
+                               mf2->v3 = mface[a].v3;
+                       }
+                       mf2->v4 = 0;
+                       mf2->flag |= ME_SMOOTH;
+
+                       test_index_face ( mf2, NULL, 0, 3 );
+               }
+
+               i++;
+       }
+
+       CDDM_calc_edges ( result );
+       CDDM_calc_normals ( result );
+
+       return result;
+
+}
+
+
+DerivedMesh *CDDM_create_tearing ( ClothModifierData *clmd, DerivedMesh *dm )
+{
+       DerivedMesh *result = NULL;
+       unsigned int i = 0, a = 0, j=0;
+       int numverts = dm->getNumVerts ( dm );
+       int numedges = dm->getNumEdges ( dm );
+       int numfaces = dm->getNumFaces ( dm );
+
+       MVert *mvert = CDDM_get_verts ( dm );
+       MEdge *medge = CDDM_get_edges ( dm );
+       MFace *mface = CDDM_get_faces ( dm );
+
+       MVert *mvert2;
+       MFace *mface2;
+       unsigned int numtris=0;
+       unsigned int numquads=0;
+       EdgeHash *edgehash = NULL;
+       Cloth *cloth = clmd->clothObject;
+       ClothSpring *springs = cloth->springs;
+       unsigned int numsprings = cloth->numsprings;
+
+       // create spring tearing hash
+       edgehash = BLI_edgehash_new();
+
+       for ( i = 0; i < numsprings; i++ )
+       {
+               if ( ( springs[i].flags & 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;
+
+       // do verts
+       mvert2 = CDDM_get_verts ( result );
+       for ( a=0; a<numverts; a++ )
+       {
+               MVert *inMV;
+               MVert *mv = &mvert2[a];
+
+               inMV = &mvert[a];
+
+               DM_copy_vert_data ( dm, result, a, a, 1 );
+               *mv = *inMV;
+       }
+
+
+       // do faces
+       mface2 = CDDM_get_faces ( result );
+       for ( a=0, i=0; a<numfaces; a++ )
+       {
+               MFace *mf = &mface2[i];
+               MFace *inMF;
+               inMF = &mface[a];
+
+               /*
+               DM_copy_face_data(dm, result, a, i, 1);
+
+               *mf = *inMF;
+               */
+
+               if ( ( !BLI_edgehash_haskey ( edgehash, mface[a].v1, mface[a].v2 ) )
+                       && ( !BLI_edgehash_haskey ( edgehash, mface[a].v2, mface[a].v3 ) )
+                       && ( !BLI_edgehash_haskey ( edgehash, mface[a].v3, mface[a].v4 ) )
+                       && ( !BLI_edgehash_haskey ( edgehash, mface[a].v4, mface[a].v1 ) ) )
+               {
+                       mf->v1 = mface[a].v1;
+                       mf->v2 = mface[a].v2;
+                       mf->v3 = mface[a].v3;
+                       mf->v4 = mface[a].v4;
+
+                       test_index_face ( mf, NULL, 0, 4 );
+
+                       i++;
+               }
+       }
+
+       CDDM_lower_num_faces ( result, i );
+       CDDM_calc_edges ( result );
+       CDDM_calc_normals ( result );
+
+       BLI_edgehash_free ( edgehash, NULL );
+
+       return result;
+}
+
+
+int cloth_cache_search_frame ( ClothModifierData *clmd, float time )
+{
+       Frame *frame = NULL;
+       LinkNode *search = NULL;
+
+       if ( clmd->clothObject )
+       {
+               search = clmd->sim_parms.cache;
+
+               while ( search )
+               {
+                       frame = ( Frame * ) search->link;
+
+                       if ( frame )
+                       {
+                               if ( frame->time == time )
+                                       return 1;
+                       }
+
+                       search = search->next;
+               }
+       }
+
+       return 0;
+
+}
+
+float cloth_cache_last_frame ( ClothModifierData *clmd )
+{
+       Frame *frame = NULL;
+       LinkNode *search = NULL;
+       float time = 0;
+
+       if ( clmd->clothObject )
+       {
+               search = clmd->sim_parms.cache;
+
+               while ( search )
+               {
+                       frame = ( Frame * ) search->link;
+
+                       if ( frame )
+                       {
+                               if ( frame->time > time )
+                                       time = frame->time;
+                       }
+               }
+       }
+       return time;
+}
+
+float cloth_cache_first_frame ( ClothModifierData *clmd )
+{
+       Frame *frame = NULL;
+       LinkNode *search = NULL;
+       float time = -1.0;
+
+       if ( clmd->clothObject )
+       {
+               search = clmd->sim_parms.cache;
+
+               while ( search )
+               {
+                       frame = ( Frame * ) search->link;
+
+                       if ( frame )
+                       {
+                               if ( time < 0.0 )
+                                       time = frame->time;
+                               else
+                               {
+                                       if ( frame->time < time )
+                                               time = frame->time;
+                               }
+                       }
+               }
+       }
+       return time;
+}
+
+void cloth_cache_get_frame ( ClothModifierData *clmd, float time )
+{
+       Frame *frame = NULL;
+       LinkNode *search = NULL;
+       float newtime = time + clmd->sim_parms.preroll;
+
+       if ( clmd->clothObject )
+       {
+               search = clmd->sim_parms.cache;
+
+               while ( search )
+               {
+                       frame = ( Frame * ) search->link;
+
+                       if ( frame )
+                       {
+                               if ( frame->time == newtime )
+                               {
+                                       // something changed, free cache!
+                                       if ( clmd->clothObject->numverts != frame->numverts )
+                                       {
+                                               cloth_cache_free ( clmd, 0 );
+                                               printf ( "clmd->clothObject->numverts != frame->numverts\n" );
+                                               return;
+                                       }
+
+                                       memcpy ( clmd->clothObject->verts, frame->verts, sizeof ( ClothVertex ) *frame->numverts );
+                                       implicit_set_positions ( clmd );
+
+                                       return;
+                               }
+                       }
+
+                       search = search->next;
+               }
+       }
+}
+
+void cloth_cache_set_frame ( ClothModifierData *clmd, float time )
+{
+       Frame *frame = NULL;
+       LinkNode *search = NULL;
+
+       if ( clmd->clothObject )
+       {
+               frame = ( Frame * ) MEM_callocN ( sizeof ( Frame ), "cloth_cache_frame" );
+
+               if ( frame )
+               {
+                       frame->time = time;
+                       frame->numverts = clmd->clothObject->numverts;
+                       frame->verts = MEM_dupallocN ( clmd->clothObject->verts );
+
+                       if ( !frame->verts )
+                       {
+                               MEM_freeN ( frame );
+                               return;
+                       }
+
+                       BLI_linklist_append ( &clmd->sim_parms.cache, frame );
+
+               }
+       }
+
+}
+
+// free cloth cache
+void cloth_cache_free ( ClothModifierData *clmd, float time )
+{
+       Frame *frame = NULL;
+       LinkNode *search = NULL, *lastsearch = NULL;
+       float newtime = time + clmd->sim_parms.preroll;
+
+       if ( time <= 2.0 )
+               newtime = time;
+
+       if ( clmd->clothObject )
+       {
+               if ( clmd->sim_parms.cache )
+               {
+                       lastsearch = search = clmd->sim_parms.cache;
+
+                       while ( search )
+                       {
+                               frame = ( Frame * ) search->link;
+
+                               if ( frame->time >= newtime )
+                               {
+                                       if ( frame->verts )
+                                       {
+                                               MEM_freeN ( frame->verts );
+                                       }
+                                       MEM_freeN ( frame );
+
+                                       lastsearch->next = search->next;
+                                       MEM_freeN ( search );
+                                       search = lastsearch->next;
+                                       lastsearch->next = NULL;
+                               }
+                               else
+                               {
+                                       lastsearch = search;
+                                       search = search->next;
+                               }
+                       }
+
+                       if ( time <= 1.0 )
+                       {
+                               clmd->sim_parms.cache = NULL;
+                       }
+
+                       if ( time <= 2.0 )
+                               clmd->sim_parms.preroll = 0;
+               }
+       }
+}
+
+
+/**
+* cloth_deform_verts - simulates one step, framenr is in frames.
+*
+**/
+DerivedMesh *clothModifier_do(ClothModifierData *clmd,
+                                        Object *ob, DerivedMesh *dm)
+{
+       unsigned int i;
+       DerivedMesh *result = NULL;
+       Cloth *cloth = clmd->clothObject;
+       unsigned int framenr = ( float ) G.scene->r.cfra;
+       float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 );
+       ListBase *effectors = NULL;
+       ClothVertex *verts = NULL;
+       Frame *frame = NULL;
+       LinkNode *search = NULL;
+       float deltaTime = current_time - clmd->sim_parms.sim_time;
+       MVert *mverts = NULL;
+       
+       result = CDDM_copy(dm);
+       
+       // only be active during a specific period:
+       // that's "first frame" and "last frame" on GUI
+       if ( clmd->clothObject )
+       {
+               if ( clmd->sim_parms.cache )
+               {
+                       if ( current_time < clmd->sim_parms.firstframe )
+                       {
+                               int frametime = cloth_cache_first_frame ( clmd );
+                               if ( cloth_cache_search_frame ( clmd, frametime ) )
+                               {
+                                       cloth_cache_get_frame ( clmd, frametime );
+                                       cloth_to_object ( ob, clmd, result );
+                               }
+                               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, result );
+                               }
+                               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, result );
+                               }
+                               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;
+       
+       if ( deltaTime == 1.0f )
+       {
+               if ( ( clmd->clothObject == NULL ) || ( dm->getNumVerts(dm) != clmd->clothObject->numverts ) )
+               {
+                       if ( !cloth_from_object ( ob, clmd, dm ) )
+                               return;
+
+                       if ( clmd->clothObject == NULL )
+                               return;
+
+                       cloth = clmd->clothObject;
+               }
+
+               clmd->clothObject->old_solver_type = clmd->sim_parms.solver_type;
+
+               // Insure we have a clmd->clothObject, in case allocation failed.
+               if ( clmd->clothObject != NULL )
+               {
+                       if ( !cloth_cache_search_frame ( clmd, framenr ) )
+                       {
+                               verts = cloth->verts;
+                               mverts = dm->getVertArray(dm);
+
+                               // Force any pinned verts to their constrained location.
+                               for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ )
+                               {
+                                       // Save the previous position.
+                                       VECCOPY ( verts->xold, verts->xconst );
+                                       VECCOPY ( verts->txold, verts->x );
+                                       // Get the current position.
+                                       VECCOPY ( verts->xconst, mverts[i].co );
+                                       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 );
+*/
+                               tend();
+                               printf ( "Cloth simulation time: %f\n", ( float ) tval() );
+
+                               cloth_cache_set_frame ( clmd, framenr );
+
+                       }
+                       else // just retrieve the cached frame
+                       {
+                               cloth_cache_get_frame ( clmd, framenr );
+                       }
+
+                       // Copy the result back to the object.
+                       cloth_to_object ( ob, clmd, result );
+
+                       // bvh_free(clmd->clothObject->tree);
+                       // clmd->clothObject->tree = bvh_build(clmd, clmd->coll_parms.epsilon);
+               }
+
+       }
+       else if ( ( deltaTime <= 0.0f ) || ( deltaTime > 1.0f ) )
+       {
+               if ( ( clmd->clothObject != NULL ) && ( clmd->sim_parms.cache ) )
+               {
+                       if ( cloth_cache_search_frame ( clmd, framenr ) )
+                       {
+                               cloth_cache_get_frame ( clmd, framenr );
+                               cloth_to_object ( ob, clmd, result );
+                       }
+               }
+       }
+       
+       if(result)
+               return result;
+       else
+               return dm;
+}
+
+/* frees all */
+void cloth_free_modifier ( ClothModifierData *clmd )
+{
+       Cloth   *cloth = NULL;
+
+       if ( !clmd )
+               return;
+
+       cloth = clmd->clothObject;
+
+       if ( ! ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT ) )
+       {
+               // free our frame cache, TODO: but get to first position before
+               cloth_cache_free ( clmd, 0 );
+
+               if ( cloth )
+               {
+
+                       // If our solver provides a free function, call it
+                       if ( cloth->old_solver_type < 255 && solvers [cloth->old_solver_type].free )
+                       {
+                               solvers [cloth->old_solver_type].free ( clmd );
+                       }
+
+                       // Free the verts.
+                       if ( cloth->verts != NULL )
+                               MEM_freeN ( cloth->verts );
+                       
+                       // Free the verts.
+                       if ( cloth->x != NULL )
+                               MEM_freeN ( cloth->x );
+                       
+                       // Free the verts.
+                       if ( cloth->xnew != NULL )
+                               MEM_freeN ( cloth->xnew );
+
+                       cloth->verts = NULL;
+                       cloth->numverts = 0;
+
+                       // Free the springs.
+                       if ( cloth->springs != NULL )
+                       {
+                               LinkNode *search = cloth->springs;
+                               while(search)
+                               {
+                                       ClothSpring *spring = search->link;
+                                                       
+                                       MEM_freeN ( spring );
+                                       search = search->next;
+                               }
+                               BLI_linklist_free(cloth->springs, NULL);
+                       
+                               cloth->springs = NULL;
+                       }
+
+                       cloth->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;
+               }
+       }
+}
+
+
+/******************************************************************************
+*
+* Internal functions.
+*
+******************************************************************************/
+
+/**
+* cloth_to_object - copies the deformed vertices to the object.
+*
+* This function is a modified version of the softbody.c:softbody_to_object() function.
+**/
+static void cloth_to_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm )
+{
+       ClothVertex     *verts = NULL;
+       unsigned int    i = 0;
+       MVert           *mvert = NULL;
+
+       if ( clmd->clothObject )
+       {
+               verts = clmd->clothObject->verts;
+               mvert = dm->getVertArray(dm);
+
+               /* inverse matrix is not uptodate... */
+               Mat4Invert ( ob->imat, ob->obmat );
+
+               for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ )
+               {
+                       VECCOPY ( mvert[i].co, verts->x );
+                       Mat4MulVecfl ( ob->imat, mvert[i].co ); /* 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 )
+{
+       unsigned int i = 0;
+       unsigned int j = 0;
+       MDeformVert *dvert = NULL;
+       Cloth *clothObj = NULL;
+       unsigned int numverts = dm->getNumVerts ( dm );
+       float goalfac = 0;
+       ClothVertex *verts = NULL;
+
+       clothObj = clmd->clothObject;
+
+       if ( !dm )
+               return;
+
+       numverts = dm->getNumVerts ( dm );
+
+       /* vgroup is 1 based, decrement so we can match the right group. */
+       --vgroup;
+
+       verts = clothObj->verts;
+
+       for ( i = 0; i < numverts; i++, verts++ )
+       {
+               // LATER ON, support also mass painting here
+               if ( clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL )
+               {
+                       dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT );
+                       if ( dvert )
+                       {
+                               for ( j = 0; j < dvert->totweight; j++ )
+                               {
+                                       if ( dvert->dw[j].def_nr == vgroup )
+                                       {
+                                               verts->goal = dvert->dw [j].weight;
+
+                                               goalfac= ABS ( clmd->sim_parms.maxgoal - clmd->sim_parms.mingoal );
+                                               verts->goal  = ( float ) pow ( verts->goal , 4.0f );
+
+                                               if ( dvert->dw [j].weight >=SOFTGOALSNAP )
+                                               {
+                                                       verts->flags |= CVERT_FLAG_PINNED;
+                                               }
+
+                                               // TODO enable mass painting here, for the moment i let "goals" go first
+
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+
+// only meshes supported at the moment
+static int cloth_from_object ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm )
+{
+       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;
+       }
+
+       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 )
+                       {
+                               /* create springs */
+                               clmd->clothObject->springs = NULL;
+                               clmd->clothObject->numsprings = -1;
+
+                               if ( !cloth_build_springs ( clmd->clothObject, dm ) )
+                               {
+                                       modifier_setError ( & ( clmd->modifier ), "Can't build springs." );
+                                       return 0;
+                               }
+
+                               mvert = dm->getVertArray ( dm ); // CDDM_get_verts ( dm );
+                               verts = clmd->clothObject->verts;
+
+                               /* set initial values */
+                               for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ )
+                               {
+                                       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
+                                               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 );
+                               }
+
+                               // 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 ( dm, clmd->coll_parms.epsilon );
+
+                               cloth_cache_set_frame ( clmd, 1 );
+                       }
+
+                       return 1;
+               case OB_LATTICE:
+                       printf ( "Not supported: OB_LATTICE\n" );
+                       // lattice_to_softbody(ob);
+                       return 1;
+               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 )
+{
+       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 ( MVert ) * clmd->clothObject->numverts, "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->xnew = MEM_callocN ( sizeof ( MVert ) * clmd->clothObject->numverts, "Cloth MVert_xnew" );
+       if ( clmd->clothObject->xnew == NULL )
+       {
+               cloth_free_modifier ( clmd );
+               modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->xnew." );
+               return;
+       }
+
+       // save face information
+       clmd->clothObject->numfaces = numfaces;
+       clmd->clothObject->mfaces = MEM_callocN ( sizeof ( MFace ) * clmd->clothObject->numfaces, "clothMFaces" );
+       if ( clmd->clothObject->mfaces == NULL )
+       {
+               cloth_free_modifier ( clmd );
+               modifier_setError ( & ( clmd->modifier ), "Out of memory on allocating clmd->clothObject->mfaces." );
+               return;
+       }
+       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 );
+
+}
+
+/***************************************************************************************
+* SPRING NETWORK BUILDING IMPLEMENTATION BEGIN
+***************************************************************************************/
+
+// be carefull: implicit solver has to be resettet when using this one!
+int cloth_add_spring ( ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type)
+{
+       Cloth *cloth = clmd->clothObject;
+       ClothSpring *spring = NULL;
+       
+       if(cloth)
+       {
+               // TODO: look if this spring is already there
+               
+               spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+               
+               spring->ij = indexA;
+               spring->kl = indexB;
+               spring->restlen =  restlength;
+               spring->type = spring_type;
+               spring->flags = 0;
+               
+               cloth->numsprings++;
+       
+               BLI_linklist_append ( &cloth->springs, spring );
+               
+               return 1;
+       }
+       return 0;
+}
+
+int cloth_build_springs ( Cloth *cloth, DerivedMesh *dm )
+{
+       ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL;
+       unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0;
+       unsigned int i = 0;
+       unsigned int numverts = dm->getNumVerts ( dm );
+       unsigned int numedges = dm->getNumEdges ( dm );
+       unsigned int numfaces = dm->getNumFaces ( dm );
+       MVert *mvert = CDDM_get_verts ( dm );
+       MEdge *medge = CDDM_get_edges ( dm );
+       MFace *mface = CDDM_get_faces ( dm );
+       unsigned int index2 = 0; // our second vertex index
+       LinkNode **edgelist = NULL;
+       EdgeHash *edgehash = NULL;
+       LinkNode *search = NULL, *search2 = NULL;
+       float temp[3];
+
+       // error handling
+       if ( numedges==0 )
+               return 0;
+
+       cloth->springs = NULL;
+
+       edgelist = MEM_callocN ( sizeof ( LinkNode * ) * numverts, "cloth_edgelist_alloc" );
+       for ( i = 0; i < numverts; i++ )
+       {
+               edgelist[i] = NULL;
+       }
+
+       if ( cloth->springs )
+               MEM_freeN ( cloth->springs );
+
+       // create spring network hash
+       edgehash = BLI_edgehash_new();
+
+       // structural springs
+       for ( i = 0; i < numedges; i++ )
+       {
+               spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+               if ( spring )
+               {
+                       spring->ij = medge[i].v1;
+                       spring->kl = medge[i].v2;
+                       VECSUB ( temp, mvert[spring->kl].co, mvert[spring->ij].co );
+                       spring->restlen =  sqrt ( INPR ( temp, temp ) );
+                       spring->type = CLOTH_SPRING_TYPE_STRUCTURAL;
+                       spring->flags = 0;
+                       struct_springs++;
+
+                       BLI_linklist_append ( &cloth->springs, spring );
+               }
+       }
+
+       // shear springs
+       for ( i = 0; i < numfaces; i++ )
+       {
+               spring = ( ClothSpring *) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+               spring->ij = mface[i].v1;
+               spring->kl = mface[i].v3;
+               VECSUB ( temp, mvert[spring->kl].co, mvert[spring->ij].co );
+               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 ( &cloth->springs, spring );
+
+               if ( mface[i].v4 )
+               {
+                       spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+                       spring->ij = mface[i].v1;
+                       spring->kl = mface[i].v3;
+                       VECSUB ( temp, mvert[spring->kl].co, mvert[spring->ij].co );
+                               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 ( &cloth->springs, spring );
+               }
+       }
+
+       // bending springs
+       search2 = cloth->springs;
+       for ( i = struct_springs; i < struct_springs+shear_springs; i++ )
+       {
+               if ( !search2 )
+                       break;
+
+               tspring2 = search2->link;
+               search = edgelist[tspring2->kl];
+               while ( search )
+               {
+                       tspring = search->link;
+                       index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) );
+                       
+                       // check for existing spring
+                       // check also if startpoint is equal to endpoint
+                       if ( !BLI_edgehash_haskey ( edgehash, index2, tspring2->ij )
+                               && !BLI_edgehash_haskey ( edgehash, tspring2->ij, index2 )
+                               && ( index2!=tspring2->ij ) )
+                       {
+                               spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
+
+                               spring->ij = tspring2->ij;
+                               spring->kl = index2;
+                               VECSUB ( temp, mvert[index2].co, mvert[tspring2->ij].co );
+                               spring->restlen =  sqrt ( INPR ( temp, temp ) );
+                               spring->type = CLOTH_SPRING_TYPE_BENDING;
+                               BLI_edgehash_insert ( edgehash, spring->ij, index2, NULL );
+                               bend_springs++;
+
+                               BLI_linklist_append ( &cloth->springs, spring );
+                       }
+                       search = search->next;
+               }
+               search2 = search2->next;
+       }
+
+       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 );
+
+       BLI_edgehash_free ( edgehash, NULL );
+
+       return 1;
+
+} /* cloth_build_springs */
+/***************************************************************************************
+* SPRING NETWORK BUILDING IMPLEMENTATION END
+***************************************************************************************/
+
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
new file mode 100644 (file)
index 0000000..f4b0ce7
--- /dev/null
@@ -0,0 +1,380 @@
+/*  collision.c      
+* 
+*
+* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version. The Blender
+* Foundation also sells licenses for use in proprietary software under
+* the Blender License.  See http://www.blender.org/BL/ for information
+* about this.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+* The Original Code is Copyright (C) Blender Foundation
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): none yet.
+*
+* ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "MEM_guardedalloc.h"
+/* types */
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_cloth_types.h"   
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_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"
+#include "BLI_edgehash.h"
+#include "BLI_linklist.h"
+#include "BKE_collisions.h"
+#include "BKE_curve.h"
+#include "BKE_deform.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_cloth.h"
+#include "BKE_modifier.h"
+#include "BKE_utildefines.h"
+#include "BKE_DerivedMesh.h"
+#include "DNA_screen_types.h"
+#include "BSE_headerbuttons.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "mydevice.h"
+
+#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 tv[3] = {0,0,0};
+       unsigned int i = 0;
+       MVert *tempVert = collmd->current_x;
+       collmd->current_x = collmd->current_xnew;
+       collmd->current_xnew = tempVert;
+                       
+       for ( i = 0; i < collmd->numverts; i++ )
+       {
+               VECSUB(tv, collmd->xnew[i].co, collmd->x[i].co);
+               VECADDS(collmd->current_xnew[i].co, collmd->x[i].co, tv, step);
+       }
+}
+
+
+/**
+ * gsl_poly_solve_cubic -
+ *
+ * copied from SOLVE_CUBIC.C --> GSL
+ */
+#define mySWAP(a,b) { float tmp = b ; b = a ; a = tmp ; }
+
+int gsl_poly_solve_cubic (float a, float b, float c, float *x0, float *x1, float *x2)
+{
+       float q = (a * a - 3 * b);
+       float r = (2 * a * a * a - 9 * a * b + 27 * c);
+
+       float Q = q / 9;
+       float R = r / 54;
+
+       float Q3 = Q * Q * Q;
+       float R2 = R * R;
+
+       float CR2 = 729 * r * r;
+       float CQ3 = 2916 * q * q * q;
+
+       if (R == 0 && Q == 0)
+       {
+               *x0 = - a / 3 ;
+               *x1 = - a / 3 ;
+               *x2 = - a / 3 ;
+               return 3 ;
+       }
+       else if (CR2 == CQ3) 
+       {
+         /* this test is actually R2 == Q3, written in a form suitable
+               for exact computation with integers */
+
+         /* Due to finite precision some float roots may be missed, and
+               considered to be a pair of complex roots z = x +/- epsilon i
+               close to the real axis. */
+
+               float sqrtQ = sqrtf (Q);
+
+               if (R > 0)
+               {
+                       *x0 = -2 * sqrtQ  - a / 3;
+                       *x1 = sqrtQ - a / 3;
+                       *x2 = sqrtQ - a / 3;
+               }
+               else
+               {
+                       *x0 = - sqrtQ  - a / 3;
+                       *x1 = - sqrtQ - a / 3;
+                       *x2 = 2 * sqrtQ - a / 3;
+               }
+               return 3 ;
+       }
+       else if (CR2 < CQ3) /* equivalent to R2 < Q3 */
+       {
+               float sqrtQ = sqrtf (Q);
+               float sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
+               float theta = acosf (R / sqrtQ3);
+               float norm = -2 * sqrtQ;
+               *x0 = norm * cosf (theta / 3) - a / 3;
+               *x1 = norm * cosf ((theta + 2.0 * M_PI) / 3) - a / 3;
+               *x2 = norm * cosf ((theta - 2.0 * M_PI) / 3) - a / 3;
+      
+               /* Sort *x0, *x1, *x2 into increasing order */
+
+               if (*x0 > *x1)
+                       mySWAP(*x0, *x1) ;
+      
+               if (*x1 > *x2)
+               {
+                       mySWAP(*x1, *x2) ;
+          
+                       if (*x0 > *x1)
+                               mySWAP(*x0, *x1) ;
+               }
+      
+               return 3;
+       }
+       else
+       {
+               float sgnR = (R >= 0 ? 1 : -1);
+               float A = -sgnR * powf (fabs (R) + sqrtf (R2 - Q3), 1.0/3.0);
+               float B = Q / A ;
+               *x0 = A + B - a / 3;
+               return 1;
+       }
+}
+
+
+/**
+ * gsl_poly_solve_quadratic
+ *
+ * copied from GSL
+ */
+int gsl_poly_solve_quadratic (float a, float b, float c,  float *x0, float *x1)
+{
+       float disc = b * b - 4 * a * c;
+
+       if (disc > 0)
+       {
+               if (b == 0)
+               {
+                       float r = fabs (0.5 * sqrtf (disc) / a);
+                       *x0 = -r;
+                       *x1 =  r;
+               }
+               else
+               {
+                       float sgnb = (b > 0 ? 1 : -1);
+                       float temp = -0.5 * (b + sgnb * sqrtf (disc));
+                       float r1 = temp / a ;
+                       float r2 = c / temp ;
+
+                       if (r1 < r2) 
+                       {
+                               *x0 = r1 ;
+                               *x1 = r2 ;
+                       } 
+                       else 
+                       {
+                               *x0 = r2 ;
+                               *x1 = r1 ;
+                       }
+               }
+               return 2;
+       }
+       else if (disc == 0) 
+       {
+               *x0 = -0.5 * b / a ;
+               *x1 = -0.5 * b / a ;
+               return 2 ;
+       }
+       else
+       {
+               return 0;
+       }
+}
+
+
+
+/*
+ * See Bridson et al. "Robust Treatment of Collision, Contact and Friction for Cloth Animation"
+ *     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 num_sols = 0;
+       
+       float g = -a[2] * c[1] * e[0] + a[1] * c[2] * e[0] +
+                       a[2] * c[0] * e[1] - a[0] * c[2] * e[1] -
+                       a[1] * c[0] * e[2] + a[0] * c[1] * e[2];
+
+       float h = -b[2] * c[1] * e[0] + b[1] * c[2] * e[0] - a[2] * d[1] * e[0] +
+                       a[1] * d[2] * e[0] + b[2] * c[0] * e[1] - b[0] * c[2] * e[1] +
+                       a[2] * d[0] * e[1] - a[0] * d[2] * e[1] - b[1] * c[0] * e[2] +
+                       b[0] * c[1] * e[2] - a[1] * d[0] * e[2] + a[0] * d[1] * e[2] -
+                       a[2] * c[1] * f[0] + a[1] * c[2] * f[0] + a[2] * c[0] * f[1] -
+                       a[0] * c[2] * f[1] - a[1] * c[0] * f[2] + a[0] * c[1] * f[2];
+
+       float i = -b[2] * d[1] * e[0] + b[1] * d[2] * e[0] +
+                       b[2] * d[0] * e[1] - b[0] * d[2] * e[1] -
+                       b[1] * d[0] * e[2] + b[0] * d[1] * e[2] -
+                       b[2] * c[1] * f[0] + b[1] * c[2] * f[0] -
+                       a[2] * d[1] * f[0] + a[1] * d[2] * f[0] +
+                       b[2] * c[0] * f[1] - b[0] * c[2] * f[1] + 
+                       a[2] * d[0] * f[1] - a[0] * d[2] * f[1] -
+                       b[1] * c[0] * f[2] + b[0] * c[1] * f[2] -
+                       a[1] * d[0] * f[2] + a[0] * d[1] * f[2];
+
+       float j = -b[2] * d[1] * f[0] + b[1] * d[2] * f[0] +
+                       b[2] * d[0] * f[1] - b[0] * d[2] * f[1] -
+                       b[1] * d[0] * f[2] + b[0] * d[1] * f[2];
+
+       // Solve cubic equation to determine times t1, t2, t3, when the collision will occur.
+       if(ABS(j) > ALMOST_ZERO)
+       {
+               i /= j;
+               h /= j;
+               g /= j;
+               
+               num_sols = gsl_poly_solve_cubic(i, h, g, &solution[0], &solution[1], &solution[2]);
+       }
+       else if(ABS(i) > ALMOST_ZERO)
+       {       
+               num_sols = gsl_poly_solve_quadratic(i, h, g, &solution[0], &solution[1]);
+               solution[2] = -1.0;
+       }
+       else if(ABS(h) > ALMOST_ZERO)
+       {
+               solution[0] = -g / h;
+               solution[1] = solution[2] = -1.0;
+               num_sols = 1;
+       }
+       else if(ABS(g) > ALMOST_ZERO)
+       {
+               solution[0] = 0;
+               solution[1] = solution[2] = -1.0;
+               num_sols = 1;
+       }
+
+       // Discard negative solutions
+       if ((num_sols >= 1) && (solution[0] < 0)) 
+       {
+               --num_sols;
+               solution[0] = solution[num_sols];
+       }
+       if ((num_sols >= 2) && (solution[1] < 0)) 
+       {
+               --num_sols;
+               solution[1] = solution[num_sols];
+       }
+       if ((num_sols == 3) && (solution[2] < 0)) 
+       {
+               --num_sols;
+       }
+
+       // Sort
+       if (num_sols == 2) 
+       {
+               if (solution[0] > solution[1]) 
+               {
+                       double tmp = solution[0];
+                       solution[0] = solution[1];
+                       solution[1] = tmp;
+               }
+       }
+       else if (num_sols == 3) 
+       {
+
+               // Bubblesort
+               if (solution[0] > solution[1]) {
+                       double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp;
+               }
+               if (solution[1] > solution[2]) {
+                       double tmp = solution[1]; solution[1] = solution[2]; solution[2] = tmp;
+               }
+               if (solution[0] > solution[1]) {
+                       double tmp = solution[0]; solution[0] = solution[1]; solution[1] = tmp;
+               }
+       }
+
+       return num_sols;
+}
+
+// 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)
+{
+       double  tempV1[3], tempV2[3], tempV4[3];
+       double  a,b,c,d,e,f;
+
+       VECSUB (tempV1, p1, p3);        
+       VECSUB (tempV2, p2, p3);        
+       VECSUB (tempV4, pv, p3);        
+       
+       a = INPR (tempV1, tempV1);      
+       b = INPR (tempV1, tempV2);      
+       c = INPR (tempV2, tempV2);      
+       e = INPR (tempV1, tempV4);      
+       f = INPR (tempV2, tempV4);      
+       
+       d = (a * c - b * b);
+       
+       if (ABS(d) < ALMOST_ZERO) {
+               *w1 = *w2 = *w3 = 1.0 / 3.0;
+               return;
+       }
+       
+       w1[0] = (float)((e * c - b * f) / d);
+       
+       if(w1[0] < 0)
+               w1[0] = 0;
+       
+       w2[0] = (float)((f - b * (double)w1[0]) / c);
+       
+       if(w2[0] < 0)
+               w2[0] = 0;
+       
+       w3[0] = 1.0f - w1[0] - w2[0];
+}
+
+DO_INLINE void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3) 
+{
+       to[0] = to[1] = to[2] = 0;
+       VECADDMUL(to, v1, w1);
+       VECADDMUL(to, v2, w2);
+       VECADDMUL(to, v3, w3);
+}
+
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
new file mode 100644 (file)
index 0000000..f61e2d2
--- /dev/null
@@ -0,0 +1,2426 @@
+/*  implicit.c      
+* 
+*
+* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version. The Blender
+* Foundation also sells licenses for use in proprietary software under
+* the Blender License.  See http://www.blender.org/BL/ for information
+* about this.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+* The Original Code is Copyright (C) Blender Foundation
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): none yet.
+*
+* ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "MEM_guardedalloc.h"
+/* types */
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"  
+#include "DNA_cloth_types.h"   
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_meshdata_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"
+#include "BLI_threads.h"
+#include "BKE_collisions.h"
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_object.h"
+#include "BKE_cloth.h"
+#include "BKE_modifier.h"
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include  "BIF_editdeform.h"
+
+
+#ifdef _WIN32
+#include <windows.h>
+static LARGE_INTEGER _itstart, _itend;
+static LARGE_INTEGER ifreq;
+void itstart(void)
+{
+       static int first = 1;
+       if(first) {
+               QueryPerformanceFrequency(&ifreq);
+               first = 0;
+       }
+       QueryPerformanceCounter(&_itstart);
+}
+void itend(void)
+{
+       QueryPerformanceCounter(&_itend);
+}
+double itval()
+{
+       return ((double)_itend.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)
+{
+       gettimeofday(&_itstart, &itz);
+}
+void itend(void)
+{
+       gettimeofday(&_itend,&itz);
+}
+double itval()
+{
+       double t1, t2;
+       t1 =  (double)_itstart.tv_sec + (double)_itstart.tv_usec/(1000*1000);
+       t2 =  (double)_itend.tv_sec + (double)_itend.tv_usec/(1000*1000);
+       return t2-t1;
+}
+#endif
+/*
+#define C99
+#ifdef C99
+#defineDO_INLINE inline 
+#else 
+#defineDO_INLINE static 
+#endif
+*/
+struct Cloth;
+
+//////////////////////////////////////////
+/* fast vector / matrix library, enhancements are welcome :) -dg */
+/////////////////////////////////////////
+
+/* DEFINITIONS */
+typedef float lfVector[3];
+typedef struct fmatrix3x3 {
+       float m[3][3]; /* 4x4 matrix */
+       unsigned int c,r; /* column and row number */
+       int pinned; /* is this vertex allowed to move? */
+       float n1,n2,n3; /* three normal vectors for collision constrains */
+       unsigned int vcount; /* vertex count */
+       unsigned int scount; /* spring count */ 
+} fmatrix3x3;
+
+///////////////////////////
+// float[3] vector
+///////////////////////////
+/* simple vector code */
+/* STATUS: verified */
+DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar)
+{
+       to[0] = from[0] * scalar;
+       to[1] = from[1] * scalar;
+       to[2] = from[2] * scalar;
+}
+/* simple cross product */
+/* STATUS: verified */
+DO_INLINE void cross_fvector(float to[3], float vectorA[3], float vectorB[3])
+{
+       to[0] = vectorA[1] * vectorB[2] - vectorA[2] * vectorB[1];
+       to[1] = vectorA[2] * vectorB[0] - vectorA[0] * vectorB[2];
+       to[2] = vectorA[0] * vectorB[1] - vectorA[1] * vectorB[0];
+}
+/* simple v^T * v product ("outer product") */
+/* STATUS: HAS TO BE verified (*should* work) */
+DO_INLINE void mul_fvectorT_fvector(float to[3][3], float vectorA[3], float vectorB[3])
+{
+       mul_fvector_S(to[0], vectorB, vectorA[0]);
+       mul_fvector_S(to[1], vectorB, vectorA[1]);
+       mul_fvector_S(to[2], vectorB, vectorA[2]);
+}
+/* simple v^T * v product with scalar ("outer product") */
+/* STATUS: HAS TO BE verified (*should* work) */
+DO_INLINE void mul_fvectorT_fvectorS(float to[3][3], float vectorA[3], float vectorB[3], float aS)
+{
+       mul_fvector_S(to[0], vectorB, vectorA[0]* aS);
+       mul_fvector_S(to[1], vectorB, vectorA[1]* aS);
+       mul_fvector_S(to[2], vectorB, vectorA[2]* aS);
+}
+
+/* printf vector[3] on console: for debug output */
+void print_fvector(float m3[3])
+{
+       printf("%f\n%f\n%f\n\n",m3[0],m3[1],m3[2]);
+}
+
+///////////////////////////
+// long float vector float (*)[3]
+///////////////////////////
+/* print long vector on console: for debug output */
+DO_INLINE void print_lfvector(float (*fLongVector)[3], unsigned int verts)
+{
+       unsigned int i = 0;
+       for(i = 0; i < verts; i++)
+       {
+               print_fvector(fLongVector[i]);
+       }
+}
+/* create long vector */
+DO_INLINE lfVector *create_lfvector(unsigned int verts)
+{
+       // TODO: check if memory allocation was successfull */
+       return  (lfVector *)MEM_callocN (verts * sizeof(lfVector), "cloth_implicit_alloc_vector");
+       // return (lfVector *)cloth_aligned_malloc(&MEMORY_BASE, verts * sizeof(lfVector));
+}
+/* delete long vector */
+DO_INLINE void del_lfvector(float (*fLongVector)[3])
+{
+       if (fLongVector != NULL)
+       {
+               MEM_freeN (fLongVector);
+               // cloth_aligned_free(&MEMORY_BASE, fLongVector);
+       }
+}
+/* copy long vector */
+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(float (*fLongVector)[3], float vector[3], unsigned int verts)
+{
+       unsigned int i = 0;
+       for(i = 0; i < verts; i++)
+       {
+               VECCOPY(fLongVector[i], vector);
+       }
+}
+/* zero long vector with float[3] */
+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], float (*fLongVector)[3], float scalar, unsigned int verts)
+{
+       unsigned int i = 0;
+
+       for(i = 0; i < verts; i++)
+       {
+               mul_fvector_S(to[i], fLongVector[i], scalar);
+       }
+}
+/* multiply long vector with scalar*/
+/* A -= B * float */
+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++)
+       {
+               VECSUBMUL(to[i], fLongVector[i], scalar);
+       }
+}
+/* dot product for big vector */
+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)
+       for(i = 0; i < verts; i++)
+       {
+               temp += INPR(fLongVectorA[i], fLongVectorB[i]);
+       }
+       return temp;
+}
+/* A = B + C  --> for big vector */
+DO_INLINE void add_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts)
+{
+       unsigned int i = 0;
+
+       for(i = 0; i < verts; i++)
+       {
+               VECADD(to[i], fLongVectorA[i], fLongVectorB[i]);
+       }
+
+}
+/* A = B + C * float --> for big vector */
+DO_INLINE void add_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++)
+       {
+               VECADDS(to[i], fLongVectorA[i], fLongVectorB[i], bS);
+
+       }
+}
+/* A = B * float + C * float --> for big vector */
+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;
+
+       for(i = 0; i < verts; i++)
+       {
+               VECADDSS(to[i], fLongVectorA[i], aS, fLongVectorB[i], bS);
+       }
+}
+/* A = B - C * float --> for big vector */
+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++)
+       {
+               VECSUBS(to[i], fLongVectorA[i], fLongVectorB[i], bS);
+       }
+
+}
+/* A = B - C --> for big vector */
+DO_INLINE void sub_lfvector_lfvector(float (*to)[3], float (*fLongVectorA)[3], float (*fLongVectorB)[3], unsigned int verts)
+{
+       unsigned int i = 0;
+
+       for(i = 0; i < verts; i++)
+       {
+               VECSUB(to[i], fLongVectorA[i], fLongVectorB[i]);
+       }
+
+}
+///////////////////////////
+// 4x4 matrix
+///////////////////////////
+/* printf 4x4 matrix on console: for debug output */
+void print_fmatrix(float m3[3][3])
+{
+       printf("%f\t%f\t%f\n",m3[0][0],m3[0][1],m3[0][2]);
+       printf("%f\t%f\t%f\n",m3[1][0],m3[1][1],m3[1][2]);
+       printf("%f\t%f\t%f\n\n",m3[2][0],m3[2][1],m3[2][2]);
+}
+/* copy 4x4 matrix */
+DO_INLINE void cp_fmatrix(float to[3][3], float from[3][3])
+{
+       // memcpy(to, from, sizeof (float) * 9);
+       VECCOPY(to[0], from[0]);
+       VECCOPY(to[1], from[1]);
+       VECCOPY(to[2], from[2]);
+}
+/* calculate determinant of 4x4 matrix */
+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];
+}
+DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3])
+{
+       unsigned int i, j;
+       float d;
+
+       if((d=det_fmatrix(from))==0)
+       {
+               printf("can't build inverse");
+               exit(0);
+       }
+       for(i=0;i<3;i++) 
+       {
+               for(j=0;j<3;j++) 
+               {
+                       int i1=(i+1)%3;
+                       int i2=(i+2)%3;
+                       int j1=(j+1)%3;
+                       int j2=(j+2)%3;
+                       // reverse indexs i&j to take transpose
+                       to[j][i] = (from[i1][j1]*from[i2][j2]-from[i1][j2]*from[i2][j1])/d;
+                       /*
+                       if(i==j)
+                       to[i][j] = 1.0f / from[i][j];
+                       else
+                       to[i][j] = 0;
+                       */
+               }
+       }
+
+}
+
+/* 4x4 matrix multiplied by a scalar */
+/* STATUS: verified */
+DO_INLINE void mul_fmatrix_S(float matrix[3][3], float scalar)
+{
+       mul_fvector_S(matrix[0], matrix[0],scalar);
+       mul_fvector_S(matrix[1], matrix[1],scalar);
+       mul_fvector_S(matrix[2], matrix[2],scalar);
+}
+
+/* a vector multiplied by a 4x4 matrix */
+/* STATUS: verified */
+DO_INLINE void mul_fvector_fmatrix(float *to, float *from, float matrix[3][3])
+{
+       to[0] = matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2];
+       to[1] = matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2];
+       to[2] = matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2];
+}
+
+/* 4x4 matrix multiplied by a vector */
+/* STATUS: verified */
+DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][3], float *from)
+{
+       to[0] = INPR(matrix[0],from);
+       to[1] = INPR(matrix[1],from);
+       to[2] = INPR(matrix[2],from);
+}
+/* 4x4 matrix multiplied by a 4x4 matrix */
+/* STATUS: verified */
+DO_INLINE void mul_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
+{
+       mul_fvector_fmatrix(to[0], matrixA[0],matrixB);
+       mul_fvector_fmatrix(to[1], matrixA[1],matrixB);
+       mul_fvector_fmatrix(to[2], matrixA[2],matrixB);
+}
+/* 4x4 matrix addition with 4x4 matrix */
+DO_INLINE void add_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
+{
+       VECADD(to[0], matrixA[0], matrixB[0]);
+       VECADD(to[1], matrixA[1], matrixB[1]);
+       VECADD(to[2], matrixA[2], matrixB[2]);
+}
+/* 4x4 matrix add-addition with 4x4 matrix */
+DO_INLINE void addadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
+{
+       VECADDADD(to[0], matrixA[0], matrixB[0]);
+       VECADDADD(to[1], matrixA[1], matrixB[1]);
+       VECADDADD(to[2], matrixA[2], matrixB[2]);
+}
+/* 4x4 matrix sub-addition with 4x4 matrix */
+DO_INLINE void addsub_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS)
+{
+       VECADDSUBSS(to[0], matrixA[0], aS, matrixB[0], bS);
+       VECADDSUBSS(to[1], matrixA[1], aS, matrixB[1], bS);
+       VECADDSUBSS(to[2], matrixA[2], aS, matrixB[2], bS);
+}
+/* A -= B + C (4x4 matrix sub-addition with 4x4 matrix) */
+DO_INLINE void subadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
+{
+       VECSUBADD(to[0], matrixA[0], matrixB[0]);
+       VECSUBADD(to[1], matrixA[1], matrixB[1]);
+       VECSUBADD(to[2], matrixA[2], matrixB[2]);
+}
+/* A -= B*x + C*y (4x4 matrix sub-addition with 4x4 matrix) */
+DO_INLINE void subadd_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS)
+{
+       VECSUBADDSS(to[0], matrixA[0], aS, matrixB[0], bS);
+       VECSUBADDSS(to[1], matrixA[1], aS, matrixB[1], bS);
+       VECSUBADDSS(to[2], matrixA[2], aS, matrixB[2], bS);
+}
+/* A = B - C (4x4 matrix subtraction with 4x4 matrix) */
+DO_INLINE void sub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
+{
+       VECSUB(to[0], matrixA[0], matrixB[0]);
+       VECSUB(to[1], matrixA[1], matrixB[1]);
+       VECSUB(to[2], matrixA[2], matrixB[2]);
+}
+/* A += B - C (4x4 matrix add-subtraction with 4x4 matrix) */
+DO_INLINE void addsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
+{
+       VECADDSUB(to[0], matrixA[0], matrixB[0]);
+       VECADDSUB(to[1], matrixA[1], matrixB[1]);
+       VECADDSUB(to[2], matrixA[2], matrixB[2]);
+}
+/////////////////////////////////////////////////////////////////
+// special functions
+/////////////////////////////////////////////////////////////////
+/* a vector multiplied and added to/by a 4x4 matrix */
+DO_INLINE void muladd_fvector_fmatrix(float to[3], float from[3], float matrix[3][3])
+{
+       to[0] += matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2];
+       to[1] += matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2];
+       to[2] += matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2];
+}
+/* 4x4 matrix multiplied and added  to/by a 4x4 matrix  and added to another 4x4 matrix */
+DO_INLINE void muladd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
+{
+       muladd_fvector_fmatrix(to[0], matrixA[0],matrixB);
+       muladd_fvector_fmatrix(to[1], matrixA[1],matrixB);
+       muladd_fvector_fmatrix(to[2], matrixA[2],matrixB);
+}
+/* a vector multiplied and sub'd to/by a 4x4 matrix */
+DO_INLINE void mulsub_fvector_fmatrix(float to[3], float from[3], float matrix[3][3])
+{
+       to[0] -= matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2];
+       to[1] -= matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2];
+       to[2] -= matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2];
+}
+/* 4x4 matrix multiplied and sub'd  to/by a 4x4 matrix  and added to another 4x4 matrix */
+DO_INLINE void mulsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3])
+{
+       mulsub_fvector_fmatrix(to[0], matrixA[0],matrixB);
+       mulsub_fvector_fmatrix(to[1], matrixA[1],matrixB);
+       mulsub_fvector_fmatrix(to[2], matrixA[2],matrixB);
+}
+/* 4x4 matrix multiplied+added by a vector */
+/* STATUS: verified */
+DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][3], float from[3])
+{
+       to[0] += INPR(matrix[0],from);
+       to[1] += INPR(matrix[1],from);
+       to[2] += INPR(matrix[2],from);  
+}
+/* 4x4 matrix multiplied+sub'ed by a vector */
+DO_INLINE void mulsub_fmatrix_fvector(float to[3], float matrix[3][3], float from[3])
+{
+       to[0] -= INPR(matrix[0],from);
+       to[1] -= INPR(matrix[1],from);
+       to[2] -= INPR(matrix[2],from);
+}
+/////////////////////////////////////////////////////////////////
+
+///////////////////////////
+// SPARSE SYMMETRIC big matrix with 4x4 matrix entries
+///////////////////////////
+/* printf a big matrix on console: for debug output */
+void print_bfmatrix(fmatrix3x3 *m3)
+{
+       unsigned int i = 0;
+
+       for(i = 0; i < m3[0].vcount + m3[0].scount; i++)
+       {
+               print_fmatrix(m3[i].m);
+       }
+}
+/* create big matrix */
+DO_INLINE fmatrix3x3 *create_bfmatrix(unsigned int verts, unsigned int springs)
+{
+       // TODO: check if memory allocation was successfull */
+       fmatrix3x3 *temp = (fmatrix3x3 *)MEM_callocN (sizeof (fmatrix3x3) * (verts + springs), "cloth_implicit_alloc_matrix");
+       temp[0].vcount = verts;
+       temp[0].scount = springs;
+       return temp;
+}
+/* delete big matrix */
+DO_INLINE void del_bfmatrix(fmatrix3x3 *matrix)
+{
+       if (matrix != NULL)
+       {
+               MEM_freeN (matrix);
+       }
+}
+/* copy big matrix */
+DO_INLINE void cp_bfmatrix(fmatrix3x3 *to, fmatrix3x3 *from)
+{      
+       // TODO bounds checking 
+       memcpy(to, from, sizeof(fmatrix3x3) * (from[0].vcount+from[0].scount) );
+}
+/* init the diagonal of big matrix */
+// slow in parallel
+DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][3])
+{
+       unsigned int i,j;
+       float tmatrix[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
+
+       for(i = 0; i < matrix[0].vcount; i++)
+       {               
+               cp_fmatrix(matrix[i].m, m3); 
+       }
+       for(j = matrix[0].vcount; j < matrix[0].vcount+matrix[0].scount; j++)
+       {
+               cp_fmatrix(matrix[j].m, tmatrix); 
+       }
+}
+/* init big matrix */
+DO_INLINE void init_bfmatrix(fmatrix3x3 *matrix, float m3[3][3])
+{
+       unsigned int i;
+
+       for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++)
+       {
+               cp_fmatrix(matrix[i].m, m3); 
+       }
+}
+/* multiply big matrix with scalar*/
+DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar)
+{
+       unsigned int i = 0;
+       for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++)
+       {
+               mul_fmatrix_S(matrix[i].m, scalar);
+       }
+}
+/* SPARSE SYMMETRIC multiply big matrix with long vector*/
+/* STATUS: verified */
+DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, float (*fLongVector)[3])
+{
+       unsigned int i = 0;
+       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]);       
+       }
+
+       /* 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++)
+       {
+               // 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]);  
+       }
+}
+/* SPARSE SYMMETRIC add big matrix with big matrix: A = B + C*/
+DO_INLINE void add_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from,  fmatrix3x3 *matrix)
+{
+       unsigned int i = 0;
+
+       /* process diagonal elements */
+       for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++)
+       {
+               add_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m);   
+       }
+
+}
+/* SPARSE SYMMETRIC add big matrix with big matrix: A += B + C */
+DO_INLINE void addadd_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from,  fmatrix3x3 *matrix)
+{
+       unsigned int i = 0;
+
+       /* process diagonal elements */
+       for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++)
+       {
+               addadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m);        
+       }
+
+}
+/* SPARSE SYMMETRIC subadd big matrix with big matrix: A -= B + C */
+DO_INLINE void subadd_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from,  fmatrix3x3 *matrix)
+{
+       unsigned int i = 0;
+
+       /* process diagonal elements */
+       for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++)
+       {
+               subadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m);        
+       }
+
+}
+/*  A = B - C (SPARSE SYMMETRIC sub big matrix with big matrix) */
+DO_INLINE void sub_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from,  fmatrix3x3 *matrix)
+{
+       unsigned int i = 0;
+
+       /* process diagonal elements */
+       for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++)
+       {
+               sub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m);   
+       }
+
+}
+/* SPARSE SYMMETRIC sub big matrix with big matrix S (special constraint matrix with limited entries) */
+DO_INLINE void sub_bfmatrix_Smatrix( fmatrix3x3 *to, fmatrix3x3 *from,  fmatrix3x3 *matrix)
+{
+       unsigned int i = 0;
+
+       /* process diagonal elements */
+       for(i = 0; i < matrix[0].vcount; i++)
+       {
+               sub_fmatrix_fmatrix(to[matrix[i].c].m, from[matrix[i].c].m, matrix[i].m);       
+       }
+
+}
+/* A += B - C (SPARSE SYMMETRIC addsub big matrix with big matrix) */
+DO_INLINE void addsub_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from,  fmatrix3x3 *matrix)
+{
+       unsigned int i = 0;
+
+       /* process diagonal elements */
+       for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++)
+       {
+               addsub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m);        
+       }
+
+}
+/* SPARSE SYMMETRIC sub big matrix with big matrix*/
+/* A -= B * float + C * float --> for big matrix */
+/* VERIFIED */
+DO_INLINE void subadd_bfmatrixS_bfmatrixS( fmatrix3x3 *to, fmatrix3x3 *from, float aS,  fmatrix3x3 *matrix, float bS)
+{
+       unsigned int i = 0;
+
+       /* process diagonal elements */
+       for(i = 0; i < matrix[0].vcount+matrix[0].scount; i++)
+       {
+               subadd_fmatrixS_fmatrixS(to[i].m, from[i].m, aS, matrix[i].m, bS);      
+       }
+
+}
+
+///////////////////////////////////////////////////////////////////
+// simulator start
+///////////////////////////////////////////////////////////////////
+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, *olddV, *F, *B, *dV, *z;
+       fmatrix3x3 *A, *dFdV, *dFdX, *S, *P, *Pinv, *bigI; 
+} Implicit_Data;
+
+int implicit_init (Object *ob, ClothModifierData *clmd)
+{
+       unsigned int i = 0;
+       unsigned int pinned = 0;
+       Cloth *cloth = NULL;
+       ClothVertex *verts = NULL;
+       ClothSpring *spring = NULL;
+       Implicit_Data *id = NULL;
+       LinkNode *search = NULL;
+
+       // init memory guard
+       // MEMORY_BASE.first = MEMORY_BASE.last = NULL;
+
+       cloth = (Cloth *)clmd->clothObject;
+       verts = cloth->verts;
+
+       // create implicit base
+       id = (Implicit_Data *)MEM_callocN (sizeof(Implicit_Data), "implicit vecmat");
+       cloth->implicit = id;
+
+       /* process diagonal elements */         
+       id->A = create_bfmatrix(cloth->numverts, cloth->numsprings);
+       id->dFdV = create_bfmatrix(cloth->numverts, cloth->numsprings);
+       id->dFdX = create_bfmatrix(cloth->numverts, cloth->numsprings);
+       id->S = create_bfmatrix(cloth->numverts, 0);
+       id->Pinv = create_bfmatrix(cloth->numverts, cloth->numsprings);
+       id->P = create_bfmatrix(cloth->numverts, cloth->numsprings);
+       id->bigI = create_bfmatrix(cloth->numverts, cloth->numsprings); // TODO 0 springs
+       id->X = create_lfvector(cloth->numverts);
+       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);
+       id->z = create_lfvector(cloth->numverts);
+       
+       for(i=0;i<cloth->numverts;i++) 
+       {
+               id->A[i].r = id->A[i].c = id->dFdV[i].r = id->dFdV[i].c = id->dFdX[i].r = id->dFdX[i].c = id->P[i].c = id->P[i].r = id->Pinv[i].c = id->Pinv[i].r = id->bigI[i].c = id->bigI[i].r = i;
+
+               if(verts [i].goal >= SOFTGOALSNAP)
+               {
+                       id->S[pinned].pinned = 1;
+                       id->S[pinned].c = id->S[pinned].r = i;
+                       pinned++;
+               }
+       }
+
+       // S is special and needs specific vcount and scount
+       id->S[0].vcount = pinned; id->S[0].scount = 0;
+
+       // init springs */
+       search = cloth->springs;
+       for(i=0;i<cloth->numsprings;i++) 
+       {
+               spring = search->link;
+               
+               // dFdV_start[i].r = big_I[i].r = big_zero[i].r = 
+               id->A[i+cloth->numverts].r = id->dFdV[i+cloth->numverts].r = id->dFdX[i+cloth->numverts].r = 
+                               id->P[i+cloth->numverts].r = id->Pinv[i+cloth->numverts].r = id->bigI[i+cloth->numverts].r = spring->ij;
+
+               // 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;
+
+               spring->matrix_index = i + cloth->numverts;
+               
+               search = search->next;
+       }
+
+       for(i = 0; i < cloth->numverts; i++)
+       {               
+               VECCOPY(id->X[i], verts[i].x);
+       }
+
+       return 1;
+}
+int    implicit_free (ClothModifierData *clmd)
+{
+       Implicit_Data *id;
+       Cloth *cloth;
+       cloth = (Cloth *)clmd->clothObject;
+
+       if(cloth)
+       {
+               id = cloth->implicit;
+
+               if(id)
+               {
+                       del_bfmatrix(id->A);
+                       del_bfmatrix(id->dFdV);
+                       del_bfmatrix(id->dFdX);
+                       del_bfmatrix(id->S);
+                       del_bfmatrix(id->P);
+                       del_bfmatrix(id->Pinv);
+                       del_bfmatrix(id->bigI);
+
+                       del_lfvector(id->X);
+                       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);
+                       del_lfvector(id->z);
+
+                       MEM_freeN(id);
+               }
+       }
+
+       return 1;
+}
+
+DO_INLINE float fb(float length, float L)
+{
+       float x = length/L;
+       return (-11.541f*pow(x,4)+34.193f*pow(x,3)-39.083f*pow(x,2)+23.116f*x-9.713f);
+}
+
+DO_INLINE float fbderiv(float length, float L)
+{
+       float x = length/L;
+
+       return (-46.164f*pow(x,3)+102.579f*pow(x,2)-78.166f*x+23.116f);
+}
+
+DO_INLINE float fbstar(float length, float L, float kb, float cb)
+{
+       float tempfb = kb * fb(length, L);
+
+       float fbstar = cb * (length - L);
+
+       if(tempfb < fbstar)
+               return fbstar;
+       else
+               return tempfb;          
+}
+
+DO_INLINE float fbstar_jacobi(float length, float L, float kb, float cb)
+{
+       float tempfb = kb * fb(length, L);
+       float fbstar = cb * (length - L);
+
+       if(tempfb < fbstar)
+       {               
+               return cb;
+       }
+       else
+       {
+               return kb * fbderiv(length, L); 
+       }       
+}
+
+DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
+{
+       unsigned int i=0;
+
+       for(i=0;i<S[0].vcount;i++)
+       {
+               mul_fvector_fmatrix(V[S[i].r], V[S[i].r], S[i].m);
+       }
+}
+
+// block diagonalizer
+void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv, fmatrix3x3 *S, fmatrix3x3 *bigI)
+{
+       unsigned int i=0;
+
+       // Take only the diagonal blocks of A
+       for(i=0;i<lA[0].vcount;i++)
+       {
+               cp_fmatrix(P[i].m, lA[i].m); 
+       }
+       /*
+       // SpecialBigSMul(P, S, P);
+       for(i=0;i<S[0].vcount;i++)
+       {
+       mul_fmatrix_fmatrix(P[S[i].r].m, S[i].m, P[S[i].r].m);
+       }
+       add_bfmatrix_bfmatrix(P, P, bigI);
+       */
+       for(i=0;i<lA[0].vcount;i++)                              
+       {
+               inverse_fmatrix(Pinv[i].m, P[i].m); 
+       }               
+
+}
+
+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;
+       float conjgrad_epsilon=0.0001f, conjgrad_lasterror=0;
+       lfVector *q, *d, *tmp, *r; 
+       float s, starget, a, s_prev;
+       unsigned int numverts = lA[0].vcount;
+       q = create_lfvector(numverts);
+       d = create_lfvector(numverts);
+       tmp = create_lfvector(numverts);
+       r = create_lfvector(numverts);
+
+       // zero_lfvector(ldV, CLOTHPARTICLES);
+       filter(ldV, S);
+
+       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, ldV);
+       sub_lfvector_lfvector(r, r, tmp, numverts);
+
+       filter(r,S);
+
+       cp_lfvector(d, r, numverts);
+
+       s = dot_lfvector(r, r, numverts);
+       starget = s * sqrt(conjgrad_epsilon);
+
+       while((s>starget && conjgrad_loopcount < conjgrad_looplimit))
+       {       
+               // Mul(q,A,d); // q = A*d;
+               mul_bfmatrix_lfvector(q, lA, d);
+
+               filter(q,S);
+
+               a = s/dot_lfvector(d, q, numverts);
+
+               // X = X + d*a;
+               add_lfvector_lfvectorS(ldV, ldV, d, a, numverts);
+
+               // r = r - q*a;
+               sub_lfvector_lfvectorS(r, r, q, a, numverts);
+
+               s_prev = s;
+               s = dot_lfvector(r, r, numverts);
+
+               //d = r+d*(s/s_prev);
+               add_lfvector_lfvectorS(d, r, d, (s/s_prev), numverts);
+
+               filter(d,S);
+
+               conjgrad_loopcount++;
+       }
+       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
+}
+/*
+int cg_filtered_pre(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z, lfVector *X0, fmatrix3x3 *P, fmatrix3x3 *Pinv, float dt)
+{
+// Solves for unknown X in equation AX=B
+unsigned int conjgrad_loopcount=0, conjgrad_looplimit=100;
+float conjgrad_epsilon=0.0001f, conjgrad_lasterror=0;
+lfVector *q, *c , *tmp, *r, *s, *filterX0, *p_fb, *bhat;
+float delta0, deltanew, deltaold, alpha=0, epsilon_sqr;
+unsigned int numverts = lA[0].vcount;
+int i = 0;
+q = create_lfvector(numverts);
+c = create_lfvector(numverts);
+tmp = create_lfvector(numverts);
+r = create_lfvector(numverts);
+s = create_lfvector(numverts);
+filterX0 = create_lfvector(numverts);
+p_fb = create_lfvector(numverts);
+bhat = create_lfvector(numverts);
+
+// SpecialBigSSub(bigI, S);
+initdiag_bfmatrix(bigI, I);
+sub_bfmatrix_Smatrix(bigI, bigI, S); // TODO
+
+BuildPPinv(lA,P,Pinv,S, bigI);
+
+//////////////////////////
+// x = S*x0 + (I-S)*z 
+//////////////////////////
+// filterX0 = X0 * 1.0f;
+cp_lfvector(filterX0, X0, numverts);
+// filter(filterX0,S);
+filter(filterX0, S);
+// X = filterX0 * 1.0f;
+cp_lfvector(ldV, filterX0, numverts);
+
+// X = X + Mul(tmp, bigI, z);
+mul_bfmatrix_lfvector(tmp, bigI, z);
+add_lfvector_lfvector(ldV, ldV, tmp, numverts);
+//////////////////////////
+
+
+//////////////////////////
+// b_hat = S*(b-A*(I-S)*z) 
+//////////////////////////     
+// bhat = bigI * z;
+mul_bfmatrix_lfvector(bhat, bigI, z);
+// bhat = Mul(tmp, A, bhat);
+mul_bfmatrix_lfvector(tmp, lA, bhat);
+cp_lfvector(bhat, tmp, numverts);
+// bhat = B - bhat;
+sub_lfvector_lfvector(bhat, lB, bhat, numverts);
+// cp_lfvector(bhat, lB, numverts);
+filter(bhat,S);
+//////////////////////////
+
+//////////////////////////
+// r = S*(b - A*x)  
+//////////////////////////
+// r = B - Mul(tmp,A,X);    // just use B if X known to be zero
+mul_bfmatrix_lfvector(tmp, lA, ldV);
+sub_lfvector_lfvector(r, lB, tmp, numverts);
+// cp_lfvector(r, lB, numverts);
+filter(r,S);
+//////////////////////////
+
+
+//////////////////////////
+// (p) = c = S * P^-1 * r
+//////////////////////////
+// c = Pinv * r;
+mul_bfmatrix_lfvector(c, Pinv, r);
+filter(c,S);
+//////////////////////////     
+
+
+//////////////////////////
+// p_fb = P * bhat
+// delta0 = dot(bhat, p_fb)
+//////////////////////////
+// p_fb = P*bhat;      
+mul_bfmatrix_lfvector(p_fb, P, bhat);
+delta0 = dot_lfvector(bhat, p_fb, numverts);
+//////////////////////////
+
+
+//////////////////////////
+// deltanew = dot(r,c)
+//////////////////////////
+deltanew = dot_lfvector(r, c, numverts);
+//////////////////////////
+epsilon_sqr = conjgrad_epsilon*conjgrad_epsilon; // paper mentiones dt * 0.01
+
+while((deltanew>(epsilon_sqr*delta0))&& (conjgrad_loopcount++ < conjgrad_looplimit))
+{
+//////////////////////////
+// (s) = q = S*A*c
+//////////////////////////
+// q = A*c; 
+mul_bfmatrix_lfvector(q, lA, c);
+filter(q,S);
+//////////////////////////             
+
+//////////////////////////
+// alpha = deltanew / (c^T * q)
+//////////////////////////
+alpha = deltanew/dot_lfvector(c, q, numverts);
+//////////////////////////             
+
+//X = X + c*alpha;
+add_lfvector_lfvectorS(ldV, ldV, c, alpha, numverts);
+//r = r - q*alpha;
+sub_lfvector_lfvectorS(r, r, q, alpha, numverts);              
+
+//////////////////////////
+// (h) = s = P^-1 * r
+//////////////////////////
+// s = Pinv * r;
+mul_bfmatrix_lfvector(s, Pinv, r);
+filter(s,S);
+//////////////////////////
+
+deltaold = deltanew;
+
+// deltanew = dot(r,s);
+deltanew = dot_lfvector(r, s, numverts);
+
+//////////////////////////
+// c = S * (s + (deltanew/deltaold)*c)
+//////////////////////////     
+// c = s + c * (deltanew/deltaold);
+add_lfvector_lfvectorS(c, s, c, (deltanew/deltaold), numverts);
+filter(c,S);
+//////////////////////////
+
+}
+conjgrad_lasterror = deltanew;
+del_lfvector(q);
+del_lfvector(c);
+del_lfvector(tmp);
+del_lfvector(r);
+del_lfvector(s);
+del_lfvector(filterX0);
+del_lfvector(p_fb);
+del_lfvector(bhat);
+printf("Bconjgrad_loopcount: %d\n", conjgrad_loopcount);
+
+return conjgrad_loopcount<conjgrad_looplimit;  // true means we reached desired accuracy in given time - ie stable
+}
+*/
+
+// outer product is NOT cross product!!!
+DO_INLINE void dfdx_spring_type1(float to[3][3], float dir[3],float length,float L,float k)
+{
+       // dir is unit length direction, rest is spring's restlength, k is spring constant.
+       // return  (outerprod(dir,dir)*k + (I - outerprod(dir,dir))*(k - ((k*L)/length)));
+       float temp[3][3];
+       mul_fvectorT_fvector(temp, dir, dir);
+       sub_fmatrix_fmatrix(to, I, temp);
+       mul_fmatrix_S(to, k* (1.0f-(L/length)));
+       mul_fmatrix_S(temp, k);
+       add_fmatrix_fmatrix(to, temp, to);
+}
+
+DO_INLINE void dfdx_spring_type2(float to[3][3], float dir[3],float length,float L,float k, float cb)
+{
+       // return  outerprod(dir,dir)*fbstar_jacobi(length, L, k, cb);
+       mul_fvectorT_fvectorS(to, dir, dir, fbstar_jacobi(length, L, k, cb));
+}
+
+DO_INLINE void dfdv_damp(float to[3][3], float dir[3], float damping)
+{
+       // derivative of force wrt velocity.  
+       // return outerprod(dir,dir) * damping;
+       mul_fvectorT_fvectorS(to, dir, dir, damping);
+}
+
+DO_INLINE void dfdx_spring(float to[3][3],  float dir[3],float length,float L,float k)
+{
+       // dir is unit length direction, rest is spring's restlength, k is spring constant.
+       //return  ( (I-outerprod(dir,dir))*Min(1.0f,rest/length) - I) * -k;
+       mul_fvectorT_fvector(to, dir, dir);
+       sub_fmatrix_fmatrix(to, I, to);
+       mul_fmatrix_S(to, (((L/length)> 1.0f) ? (1.0f): (L/length))); 
+       sub_fmatrix_fmatrix(to, to, I);
+       mul_fmatrix_S(to, -k);
+}
+
+DO_INLINE void dfdx_damp(float to[3][3],  float dir[3],float length,const float vel[3],float rest,float damping)
+{
+       // inner spring damping   vel is the relative velocity  of the endpoints.  
+       //      return (I-outerprod(dir,dir)) * (-damping * -(dot(dir,vel)/Max(length,rest)));
+       mul_fvectorT_fvector(to, dir, dir);
+       sub_fmatrix_fmatrix(to, I, to);
+       mul_fmatrix_S(to,  (-damping * -(INPR(dir,vel)/MAX2(length,rest)))); 
+
+}
+
+DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *lF, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX)
+{
+       float extent[3];
+       float length = 0;
+       float dir[3] = {0,0,0};
+       float vel[3];
+       float k = 0.0f;
+       float L = s->restlen;
+       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);
+       cp_fmatrix(s->dfdv, nulldfdx);
+
+       // calculate elonglation
+       VECSUB(extent, X[s->kl], X[s->ij]);
+       VECSUB(vel, V[s->kl], V[s->ij]);
+       length = sqrt(INPR(extent, extent));
+       
+       s->flags &= ~CLOTH_SPRING_FLAG_NEEDED;
+       
+       if(length > ABS(ALMOST_ZERO))
+       {
+               /*
+               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;
+                       }
+               } 
+               */
+               mul_fvector_S(dir, extent, 1.0f/length);
+       }
+       else    
+       {
+               mul_fvector_S(dir, extent, 0.0f);
+       }
+       
+       
+       // calculate force of structural + shear springs
+       if(s->type != CLOTH_SPRING_TYPE_BENDING)
+       {
+               if(length > L) // only on elonglation
+               {
+                       s->flags |= CLOTH_SPRING_FLAG_NEEDED;
+
+                       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 * ((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);
+               }
+       }
+       else // calculate force of bending springs
+       {
+               if(length < L)
+               {
+                       s->flags |= CLOTH_SPRING_FLAG_NEEDED;
+                       
+                       k = clmd->sim_parms.bending;    
+
+                       mul_fvector_S(bending_force, dir, fbstar(length, L, k, cb));
+                       VECADD(s->f, s->f, bending_force);
+
+                       dfdx_spring_type2(s->dfdx, dir,length,L,k, cb);
+               }
+       }
+}
+
+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)
+       {
+               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); 
+               }
+
+               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);
+       }       
+}
+
+DO_INLINE void calculateTriangleNormal(float to[3], lfVector *X, MFace mface)
+{
+       float v1[3], v2[3];
+
+       VECSUB(v1, X[mface.v2], X[mface.v1]);
+       VECSUB(v2, X[mface.v3], X[mface.v1]);
+       cross_fvector(to, v1, v2);
+}
+
+DO_INLINE void calculatQuadNormal(float to[3], lfVector *X, MFace mface)
+{
+       float temp = CalcNormFloat4(X[mface.v1],X[mface.v2],X[mface.v3],X[mface.v4],to);
+       mul_fvector_S(to, to, temp);
+}
+
+void calculateWeightedVertexNormal(ClothModifierData *clmd, MFace *mfaces, float to[3], int index, lfVector *X)
+{
+       float temp[3]; 
+       int i;
+       Cloth *cloth = clmd->clothObject;
+
+       for(i = 0; i < cloth->numfaces; i++)
+       {
+               // check if this triangle contains the selected vertex
+               if(mfaces[i].v1 == index || mfaces[i].v2 == index || mfaces[i].v3 == index || mfaces[i].v4 == index)
+               {
+                       calculatQuadNormal(temp, X, mfaces[i]);
+                       VECADD(to, to, temp);
+               }
+       }
+}
+float calculateVertexWindForce(float wind[3], float vertexnormal[3])  
+{
+       return fabs(INPR(wind, vertexnormal) * 0.5f);
+}
+
+DO_INLINE void calc_triangle_force(ClothModifierData *clmd, MFace mface, lfVector *F, lfVector *X, lfVector *V, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors)
+{      
+
+}
+
+void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time)
+{
+       /* 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           gravity[3];
+       float           tm2[3][3]       = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}};
+       ClothVertex *verts = cloth->verts;
+       MFace           *mfaces         = cloth->mfaces;
+       float wind_normalized[3];
+       unsigned int numverts = cloth->numverts;
+       float auxvect[3], velgoal[3], tvect[3];
+       float kd, ks;
+       LinkNode *search = cloth->springs;
+
+
+       VECCOPY(gravity, clmd->sim_parms.gravity);
+       mul_fvector_S(gravity, gravity, 0.001f); /* scale gravity force */
+
+       /* set dFdX jacobi matrix to zero */
+       init_bfmatrix(dFdX, ZERO);
+       /* set dFdX jacobi matrix diagonal entries to -spring_air */ 
+       initdiag_bfmatrix(dFdV, tm2);
+
+       init_lfvector(lF, gravity, numverts);
+
+       submul_lfvectorS(lF, lV, spring_air, numverts);
+
+       /* do goal stuff */
+       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, verts[i].xconst, verts[i].xold);
+                               mul_fvector_S(tvect, tvect, time);
+                               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 ;
+                               VECADDS(lF[i], lF[i], auxvect, -ks);
+
+                               // calulate damping forces generated by goals                           
+                               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);
+                               
+                       }
+               }       
+       }
+
+       /* handle external forces like wind */
+       if(effectors)
+       {
+               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)
+               for(i = 0; i < cloth->numverts; i++)
+               {
+                       float vertexnormal[3]={0,0,0};
+                       float fieldfactor = 1000.0f, windfactor  = 250.0f; // from sb
+                       
+                       pdDoEffectors(effectors, lX[i], force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);          
+                       
+                       // TODO apply forcefields here
+                       VECADDS(lF[i], lF[i], force, fieldfactor*0.01f);
+
+                       VECCOPY(wind_normalized, speed);
+                       Normalize(wind_normalized);
+                       
+                       calculateWeightedVertexNormal(clmd, mfaces, vertexnormal, i, lX);
+                       VECADDS(lF[i], lF[i], wind_normalized, -calculateVertexWindForce(speed, vertexnormal));
+               }
+       }
+       
+       // calculate 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)){}
+               cloth_calc_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX);
+
+               search = search->next;
+       }
+       
+       // 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))    
+               cloth_apply_spring_force(clmd, search->link, lF, lX, lV, dFdV, dFdX);
+               search = search->next;
+       }
+}
+
+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;
+
+       lfVector *dFdXmV = create_lfvector(numverts);
+       initdiag_bfmatrix(A, I);
+       zero_lfvector(dV, numverts);
+
+       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);
+       
+       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);
+       
+       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, 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;
+       Implicit_Data *id = cloth->implicit;
+       int result = 0;
+       
+       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)
+                       {                       
+                               VECSUB(id->V[i], verts[i].xconst, verts[i].xold);
+                               // VecMulf(id->V[i], 1.0 / dt);
+                       }
+               }       
+       }
+
+       while(step < tf)
+       {               
+               effectors= pdInitEffectors(ob,NULL);
+               
+               // 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, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv);
+               
+               add_lfvector_lfvectorS(id->Xnew, id->X, id->Vnew, dt, numverts);
+               
+               if(clmd->coll_parms.flags & CLOTH_COLLISIONSETTINGS_FLAG_ENABLED)
+               {
+                       // collisions 
+                       // itstart();
+                       
+                       // update verts to current positions
+                       for(i = 0; i < numverts; i++)
+                       {               
+                               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, verts[i].xold);
+                                               VECCOPY(id->Xnew[i], tvect);
+                                       }
+                                               
+                               }
+                               
+                               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 = 0; // cloth_bvh_objcollision(clmd, step + dt, dt);
+       
+                       // copy corrected positions back to simulation
+                       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
+                               {
+                                       VECCOPY(verts[i].txold, id->Xnew[i]);
+                               }
+                       }
+                       
+                       // X = Xnew;
+                       cp_lfvector(id->X, id->Xnew, numverts);
+                       
+                       // if there were collisions, advance the velocity from v_n+1/2 to v_n+1
+                       if(result)
+                       {
+                               // V = Vnew;
+                               cp_lfvector(id->V, id->Vnew, numverts);
+                               
+                               // 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->olddV, id->P, id->Pinv);
+                       }
+               }
+               else
+               {
+                       // X = Xnew;
+                       cp_lfvector(id->X, id->Xnew, numverts);
+               }
+               
+               // itend();
+               // printf("collision time: %f\n", (float)itval());
+               
+               // V = Vnew;
+               cp_lfvector(id->V, id->Vnew, numverts);
+
+               step += dt;
+
+               if(effectors) pdEndEffectors(effectors);
+       }
+
+       for(i = 0; i < numverts; i++)
+       {                               
+               if(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL)
+               {
+                       if(verts [i].goal < SOFTGOALSNAP)
+                       {
+                               VECCOPY(verts[i].txold, id->X[i]);
+                               VECCOPY(verts[i].x, id->X[i]);
+                               VECCOPY(verts[i].v, id->V[i]);
+                       }
+                       else
+                       {
+                               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]);
+               }
+       }
+       return 1;
+}
+
+void implicit_set_positions (ClothModifierData *clmd)
+{              
+       Cloth *cloth = clmd->clothObject;
+       ClothVertex *verts = cloth->verts;
+       unsigned int numverts = cloth->numverts, i;
+       Implicit_Data *id = cloth->implicit;
+       
+       for(i = 0; i < numverts; i++)
+       {                               
+               VECCOPY(id->X[i], verts[i].x);
+               VECCOPY(id->V[i], verts[i].v);
+       }       
+}
+
+
+int collisions_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
+       collisions_compute_barycentric(collpair->pa,
+       cloth1->verts[collpair->ap1].txold,
+       cloth1->verts[collpair->ap2].txold,
+       cloth1->verts[collpair->ap3].txold, 
+       &w1, &w2, &w3);
+       
+       collisions_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 
+}
+                       
+
+       impulse = -2.0f * magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3);
+                       
+                       // printf("impulse: %f\n", impulse);
+                       
+                       // face A
+       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++;
+                       
+                       // face B
+       VECADDMUL(cloth2->verts[collpair->bp1].impulse, collpair->normal, u1 * impulse); 
+       cloth2->verts[collpair->bp1].impulse_count++;
+                       
+       VECADDMUL(cloth2->verts[collpair->bp2].impulse, collpair->normal, u2 * impulse); 
+       cloth2->verts[collpair->bp2].impulse_count++;
+                       
+       VECADDMUL(cloth2->verts[collpair->bp3].impulse, collpair->normal, u3 * impulse); 
+       cloth2->verts[collpair->bp3].impulse_count++;
+                       
+                       
+       result = 1;     
+               
+                       // printf("magnitude_i: %f\n", magnitude_i); // negative before collision in my case
+                       
+                       // Apply the impulse and increase impulse counters.
+       
+                       
+}
+               
+       search = search->next;
+}
+       
+       
+       return result;
+       */
+       return 0;
+}
+
+
+int collisions_collision_response_moving_tris(ClothModifierData *clmd, ClothModifierData *coll_clmd)
+{
+       
+}
+
+
+int collisions_collision_response_moving_edges(ClothModifierData *clmd, ClothModifierData *coll_clmd)
+{
+       
+}
+
+void cloth_collision_static(ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree *tree1, CollisionTree *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;
+                               
+}
+       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
+}
+                       
+}
+}
+       */
+}
+
+
+// move collision objects forward in time and update static bounding boxes
+void collisions_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 ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
+               }
+       }
+}
+
+
+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 dt)
+{
+       /*
+       Base *base=NULL;
+       ClothModifierData *coll_clmd=NULL;
+       Cloth *cloth=NULL;
+       Object *coll_ob=NULL;
+       BVH *collisions_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;
+       LinkNode *collision_list = NULL; 
+
+       if ((clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ) || !(((Cloth *)clmd->clothObject)->tree))
+       {
+               return 0;
+       }
+       cloth = clmd->clothObject;
+       verts = cloth->verts;
+       collisions_bvh = (BVH *) cloth->tree;
+       numfaces = clmd->clothObject->numfaces;
+       numverts = clmd->clothObject->numverts;
+       
+       ////////////////////////////////////////////////////////////
+       // static collisions
+       ////////////////////////////////////////////////////////////
+
+       // update cloth bvh
+       // bvh_update(clmd, collisions_bvh, 0); // 0 means STATIC, 1 means MOVING (see later in this function)
+       
+       // update collision objects
+       collisions_update_collision_objects(step);
+       
+       do
+       {
+               result = 0;
+               ic = 0;
+               
+               // 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;
+                                       
+                                       // fill collision list 
+                                       bvh_traverse(collisions_bvh->root, coll_bvh->root, collision_list);
+                                       
+                                       // 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;
+                                               
+                                               // result += collisions_collision_response_static_tris(clmd, coll_clmd, collision_list, 0);
+                       
+                                               // result += collisions_collision_response_static_tris(coll_clmd, clmd, collision_list, 1);
+                                       
+                                               // 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(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;
+                                       }
+                               }
+                               else
+                                       printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
+                       }
+               }
+               
+               printf("ic: %d\n", ic);
+               rounds++;
+       }
+       while(result && (10>rounds));// CLOTH_MAX_THRESHOLD
+       
+       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, collisions_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;
+               
+               // 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(collisions_bvh->root, coll_bvh->root, collision_list);
+                                       
+                                       // 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
+                                               
+                                               
+                                               if (coll_clmd->clothObject) 
+                                               result += collisions_collision_response_moving_tris(clmd, coll_clmd);
+                                               else
+                                               printf ("collisions_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, collisions_bvh, 1);  // 0 means STATIC, 1 means MOVING 
+               
+               
+                                       // 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;
+                                       }
+                               }
+                               else
+                                       printf ("collisions_bvh_objcollision: found a collision object with clothObject or collData NULL.\n");
+                       }
+               }
+                               
+               printf("ic: %d\n", ic);
+               rounds++;
+       }
+       while(result && (10>rounds)); // CLOTH_MAX_THRESHOLD
+       
+       
+       ////////////////////////////////////////////////////////////
+       // 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);
+       */
+}
\ No newline at end of file
diff --git a/source/blender/blenkernel/intern/kdop.c b/source/blender/blenkernel/intern/kdop.c
new file mode 100644 (file)
index 0000000..32bab0b
--- /dev/null
@@ -0,0 +1,884 @@
+/*  collision.c      
+* 
+*
+* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version. The Blender
+* Foundation also sells licenses for use in proprietary software under
+* the Blender License.  See http://www.blender.org/BL/ for information
+* about this.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+* The Original Code is Copyright (C) Blender Foundation
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): none yet.
+*
+* ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "MEM_guardedalloc.h"
+/* types */
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_key_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_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"
+#include "BLI_edgehash.h"
+#include "BLI_linklist.h"
+#include "BKE_curve.h"
+#include "BKE_deform.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_displist.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_key.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+#include "BKE_collisions.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"
+#include "BSE_headerbuttons.h"
+#include "BIF_screen.h"
+#include "BIF_space.h"
+#include "mydevice.h"
+
+
+////////////////////////////////////////////////////////////////////////
+// Additional fastened appending function
+// It uses the link to the last inserted node as start value 
+// for searching the end of the list
+// NEW: in compare to the original function, this one returns
+// the reference to the last inserted node 
+////////////////////////////////////////////////////////////////////////
+LinkNode *BLI_linklist_append_fast(LinkNode **listp, void *ptr) {
+       LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink");
+       LinkNode *node = *listp;
+
+       nlink->link = ptr;
+       nlink->next = NULL;
+
+       if(node == NULL){
+               *listp = nlink;
+       } else {
+               while(node->next != NULL){
+                       node = node->next;   
+               }
+               node->next = nlink;
+       }
+       return nlink;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+// Bounding Volume Hierarchy Definition
+// 
+// Notes: From OBB until 26-DOP --> all bounding volumes possible, just choose type below
+// Notes: You have to choose the type at compile time ITM
+// Notes: You can choose the tree type --> binary, quad, octree, choose below
+////////////////////////////////////////////////////////////////////////
+
+static float KDOP_AXES[13][3] =
+{ {1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 1, 1}, {1, -1, 1}, {1, 1, -1},
+{1, -1, -1}, {1, 1, 0}, {1, 0, 1}, {0, 1, 1}, {1, -1, 0}, {1, 0, -1},
+{0, 1, -1}
+};
+
+///////////// choose bounding volume here! /////////////
+
+// #define KDOP_26
+
+// #define KDOP_14
+
+// AABB:
+// #define KDOP_8
+
+// OBB: 
+#define KDOP_6
+
+
+
+#ifdef KDOP_26
+#define KDOP_END 13
+#define KDOP_START 0
+#endif
+
+// I didn't test this one!
+#ifdef KDOP_18
+#define KDOP_END 7
+#define KDOP_START 13
+#endif
+
+#ifdef KDOP_14
+#define KDOP_END 7
+#define KDOP_START 0
+#endif
+
+// this is basicly some AABB
+#ifdef KDOP_8
+#define KDOP_END 4
+#define KDOP_START 0
+#endif
+
+// this is basicly some OBB
+#ifdef KDOP_6
+#define KDOP_END 3
+#define KDOP_START 0
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// Introsort 
+// with permission deriven from the following Java code:
+// http://ralphunden.net/content/tutorials/a-guide-to-introsort/
+// and he derived it from the SUN STL 
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+static int size_threshold = 16;
+/*
+* Common methods for all algorithms
+*/
+void bvh_exchange(CollisionTree **a, int i, int j)
+{
+       CollisionTree *t=a[i];
+       a[i]=a[j];
+       a[j]=t;
+}
+int floor_lg(int a)
+{
+       return (int)(floor(log(a)/log(2)));
+}
+
+/*
+* Insertion sort algorithm
+*/
+static void bvh_insertionsort(CollisionTree **a, int lo, int hi, int axis)
+{
+       int i,j;
+       CollisionTree *t;
+       for (i=lo; i < hi; i++)
+       {
+               j=i;
+               t = a[i];
+               while((j!=lo) && (t->bv[axis] < (a[j-1])->bv[axis]))
+               {
+                       a[j] = a[j-1];
+                       j--;
+               }                               
+               a[j] = t;
+       }
+}
+
+static int bvh_partition(CollisionTree **a, int lo, int hi, CollisionTree *x, int axis)
+{
+       int i=lo, j=hi;
+       while (1)
+       {
+               while ((a[i])->bv[axis] < x->bv[axis]) i++;
+               j=j-1;
+               while (x->bv[axis] < (a[j])->bv[axis]) j=j-1;
+               if(!(i < j))
+                       return i;
+               bvh_exchange(a, i,j);
+               i++;
+       }
+}
+
+/*
+* Heapsort algorithm
+*/
+static void bvh_downheap(CollisionTree **a, int i, int n, int lo, int axis)
+{
+       CollisionTree *d = a[lo+i-1];
+       int child;
+       while (i<=n/2)
+       {
+               child = 2*i;
+               if ((child < n) && ((a[lo+child-1])->bv[axis] < (a[lo+child])->bv[axis]))
+               {
+                       child++;
+               }
+               if (!(d->bv[axis] < (a[lo+child-1])->bv[axis])) break;
+               a[lo+i-1] = a[lo+child-1];
+               i = child;
+       }
+       a[lo+i-1] = d;
+}
+
+static void bvh_heapsort(CollisionTree **a, int lo, int hi, int axis)
+{
+       int n = hi-lo, i;
+       for (i=n/2; i>=1; i=i-1)
+       {
+               bvh_downheap(a, i,n,lo, axis);
+       }
+       for (i=n; i>1; i=i-1)
+       {
+               bvh_exchange(a, lo,lo+i-1);
+               bvh_downheap(a, 1,i-1,lo, axis);
+       }
+}
+
+static CollisionTree *bvh_medianof3(CollisionTree **a, int lo, int mid, int hi, int axis) // returns Sortable
+{
+       if ((a[mid])->bv[axis] < (a[lo])->bv[axis])
+       {
+               if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
+                       return a[mid];
+               else
+               {
+                       if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
+                               return a[hi];
+                       else
+                               return a[lo];
+               }
+       }
+       else
+       {
+               if ((a[hi])->bv[axis] < (a[mid])->bv[axis])
+               {
+                       if ((a[hi])->bv[axis] < (a[lo])->bv[axis])
+                               return a[lo];
+                       else
+                               return a[hi];
+               }
+               else
+                       return a[mid];
+       }
+}
+/*
+* Quicksort algorithm modified for Introsort
+*/
+static void bvh_introsort_loop (CollisionTree **a, int lo, int hi, int depth_limit, int axis)
+{
+       int p;
+
+       while (hi-lo > size_threshold)
+       {
+               if (depth_limit == 0)
+               {
+                       bvh_heapsort(a, lo, hi, axis);
+                       return;
+               }
+               depth_limit=depth_limit-1;
+               p=bvh_partition(a, lo, hi, bvh_medianof3(a, lo, lo+((hi-lo)/2)+1, hi-1, axis), axis);
+               bvh_introsort_loop(a, p, hi, depth_limit, axis);
+               hi=p;
+       }
+}
+
+void bvh_sort(CollisionTree **a0, int begin, int end, int axis)
+{
+       if (begin < end)
+       {
+               CollisionTree **a=a0;
+               bvh_introsort_loop(a, begin, end, 2*floor_lg(end-begin), axis);
+               bvh_insertionsort(a, begin, end, axis);
+       }
+}
+void bvh_sort_along_axis(CollisionTree **face_list, int start, int end, int axis)
+{
+       bvh_sort(face_list, start, end, axis);
+}
+////////////////////////////////////////////////////////////////////////////////////////////////
+void bvh_free(BVH * bvh)
+{
+       LinkNode *search = NULL;
+       CollisionTree *tree = NULL;
+
+       if (bvh) 
+       {
+
+               search = bvh->tree;
+
+               while(search)
+               {
+                       LinkNode *next= search->next;
+                       tree = search->link;
+
+                       MEM_freeN(tree);
+
+                       search = next;
+               }
+
+               BLI_linklist_free(bvh->tree,NULL); 
+               bvh->tree = NULL;
+               
+               if(bvh->x)
+                       MEM_freeN(bvh->x);
+               if(bvh->xnew)
+                       MEM_freeN(bvh->xnew);
+               
+               MEM_freeN(bvh);
+               bvh = NULL;
+       }
+}
+
+// only supports x,y,z axis in the moment
+// but we should use a plain and simple function here for speed sake
+int bvh_largest_axis(float *bv)
+{
+       float middle_point[3];
+
+       middle_point[0] = (bv[1]) - (bv[0]); // x axis
+       middle_point[1] = (bv[3]) - (bv[2]); // y axis
+       middle_point[2] = (bv[5]) - (bv[4]); // z axis
+       if (middle_point[0] > middle_point[1]) 
+       {
+               if (middle_point[0] > middle_point[2])
+                       return 1; // max x axis
+               else
+                       return 5; // max z axis
+       }
+       else 
+       {
+               if (middle_point[1] > middle_point[2])
+                       return 3; // max y axis
+               else
+                       return 5; // max z axis
+       }
+}
+
+// depends on the fact that the BVH's for each face is already build
+void bvh_calc_DOP_hull_from_faces(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
+{
+       float newmin,newmax;
+       int i, j;
+       for (j = 0; j < numfaces; j++)
+       {
+               // for all Axes.
+               for (i = KDOP_START; i < KDOP_END; i++)
+               {
+                       newmin = (tri [j])->bv[(2 * i)];        
+                       if ((newmin < bv[(2 * i)]) || (j == 0))
+                       {
+                               bv[(2 * i)] = newmin;
+                       }
+
+                       newmax = (tri [j])->bv[(2 * i) + 1];
+                       if ((newmax > bv[(2 * i) + 1]) || (j == 0))
+                       {
+                               bv[(2 * i) + 1] = newmax;
+                       }
+               }
+       }
+}
+
+void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
+{
+       MVert *tempMVert = bvh->x;
+       float *tempBV = bv;
+       float newminmax;
+       int i, j, k;
+       for (j = 0; j < numfaces; j++)
+       {
+               // 1 up to 4 vertices per leaf. 
+               for (k = 0; k < 4; k++)
+               {
+                       int temp = tri[j]->point_index[k];
+                       
+                       if(temp < 0)
+                               continue;
+                       
+                       // for all Axes.
+                       for (i = KDOP_START; i < KDOP_END; i++)
+                       {                               
+                               newminmax = INPR(tempMVert[temp].co, KDOP_AXES[i]);
+                               if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
+                                       tempBV[(2 * i)] = newminmax;
+                               if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
+                                       tempBV[(2 * i) + 1] = newminmax;
+                       }
+               }
+       }
+}
+
+void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
+{
+       MVert *tempMVert = bvh->x;
+       MVert *tempMVert2 = bvh->xnew;
+       float *tempBV = bv;
+       float newminmax;
+       int i, j, k;
+       for (j = 0; j < numfaces; j++)
+       {
+               // 3 or 4 vertices per face.
+               for (k = 0; k < 4; k++)
+               {
+                       int temp = tri[j]->point_index[k];
+                       
+                       if(temp < 0)
+                               continue;
+                       
+                       // for all Axes.
+                       for (i = KDOP_START; i < KDOP_END; i++)
+                       {                               
+                               newminmax = INPR(tempMVert[temp].co, KDOP_AXES[i]);
+                               if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
+                                       tempBV[(2 * i)] = newminmax;
+                               if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
+                                       tempBV[(2 * i) + 1] = newminmax;
+                               
+                               newminmax = INPR(tempMVert2[temp].co, KDOP_AXES[i]);
+                               if ((newminmax < tempBV[(2 * i)]) || (k == 0 && j == 0))
+                                       tempBV[(2 * i)] = newminmax;
+                               if ((newminmax > tempBV[(2 * i) + 1])|| (k == 0 && j == 0))
+                                       tempBV[(2 * i) + 1] = newminmax;
+                       }
+               }
+       }
+}
+
+static void bvh_div_env_node(BVH * bvh, TreeNode *tree, CollisionTree **face_list, unsigned int start, unsigned int end, int lastaxis, LinkNode *nlink)
+{
+       int             i = 0;
+       CollisionTree *newtree = NULL;
+       int laxis = 0, max_nodes=4;
+       unsigned int tstart, tend;
+       LinkNode *nlink1 = nlink;
+       LinkNode *tnlink;
+       tree->traversed = 0;    
+       // Determine which axis to split along
+       laxis = bvh_largest_axis(tree->bv);
+
+       // Sort along longest axis
+       if(laxis!=lastaxis)
+               bvh_sort_along_axis(face_list, start, end, laxis);
+
+       max_nodes = MIN2((end-start + 1 ),4);
+
+       for (i = 0; i < max_nodes; i++)
+       {
+               tree->count_nodes++;
+
+               if(end-start > 4)
+               {
+                       int quarter = ((float)((float)(end - start + 1) / 4.0f));
+                       tstart = start + i * quarter;
+                       tend = tstart + quarter - 1;
+
+                       // be sure that we get all faces
+                       if(i==3)
+                       {
+                               tend = end;
+                       }
+               }
+               else
+               {
+                       tend = tstart = start + i;
+               }
+
+               // Build tree until 4 node left.
+               if ((tend-tstart + 1 ) > 1) 
+               {
+                       newtree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
+                       tnlink = BLI_linklist_append_fast(&nlink1->next, newtree);
+
+                       newtree->nodes[0] = newtree->nodes[1] = newtree->nodes[2] = newtree->nodes[3] = NULL;
+                       newtree->count_nodes = 0;
+                       newtree->parent = tree;
+                       newtree->isleaf = 0;
+
+                       tree->nodes[i] = newtree;
+
+                       nlink1 = tnlink;
+
+                       bvh_calc_DOP_hull_from_faces(bvh, &face_list[tstart], tend-tstart + 1, tree->nodes[i]->bv);
+
+                       bvh_div_env_node(bvh, tree->nodes[i], face_list, tstart, tend, laxis, nlink1);
+               }
+               else // ok, we have 1 left for this node
+               {
+                       CollisionTree *tnode = face_list[tstart];
+                       tree->nodes[i] = tnode;
+                       tree->nodes[i]->parent = tree;
+               }
+       }
+       return;
+}
+
+// mfaces is allowed to be null
+// just vertexes are used if mfaces=NULL
+BVH *bvh_build (BVH *bvh, MFace *mfaces, unsigned int numfaces)
+{
+       unsigned int i = 0, j = 0;
+       CollisionTree **face_list=NULL;
+       CollisionTree *tree=NULL;
+       LinkNode *nlink = NULL;
+       
+       nlink = bvh->tree;
+
+       bvh->root = bvh->tree->link;
+       bvh->root->isleaf = 0;
+       bvh->root->parent = NULL;
+       bvh->root->nodes[0] = bvh->root->nodes[1] = bvh->root->nodes[1] = bvh->root->nodes[3] = NULL;
+
+       if(bvh->numfaces<=1)
+       {
+               // Why that? --> only one face there
+               if(bvh->mfaces)
+               {
+                       bvh->root->point_index[0] = mfaces[0].v1;
+                       bvh->root->point_index[1] = mfaces[0].v2;
+                       bvh->root->point_index[2] = mfaces[0].v3;
+                       if(mfaces[0].v4)
+                               bvh->root->point_index[3] = mfaces[0].v4;
+                       else
+                               bvh->root->point_index[3] = -1;
+               }
+               else
+               {
+                       bvh->root->point_index[0] = 0;
+                       bvh->root->point_index[1] = -1;
+                       bvh->root->point_index[2] = -1;
+                       bvh->root->point_index[3] = -1;
+               }
+               
+               bvh->root->isleaf = 1;
+               bvh->root->traversed = 0;
+               bvh->root->count_nodes = 0;
+               bvh->leaf_root = bvh->root;
+               bvh->leaf_tree = bvh->root;
+               bvh->root->nextLeaf = NULL;
+               bvh->root->prevLeaf = NULL;
+       }
+       else
+       {       
+               // create face boxes            
+               face_list = MEM_callocN (bvh->numfaces * sizeof (CollisionTree *), "CollisionTree");
+               if (face_list == NULL) 
+               {
+                       printf("bvh_build: Out of memory for face_list.\n");
+                       bvh_free(bvh);
+                       return NULL;
+               }
+
+               // create face boxes
+               for(i = 0; i < bvh->numfaces; i++)
+               {
+                       LinkNode *tnlink = NULL;
+                       
+                       tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
+                       // TODO: check succesfull alloc
+
+                       tnlink = BLI_linklist_append_fast(&nlink->next, tree);
+
+                       face_list[i] = tree;
+                       
+                       if(bvh->mfaces)
+                       {
+                               bvh->root->point_index[0] = mfaces[i].v1; 
+                               bvh->root->point_index[1] = mfaces[i].v2;
+                               bvh->root->point_index[2] = mfaces[i].v3;
+                               if(mfaces[i].v4)
+                                       bvh->root->point_index[3] = mfaces[i].v4;
+                               else
+                                       bvh->root->point_index[3] = -1;
+                       }
+                       else
+                       {
+                               bvh->root->point_index[0] = i; 
+                               bvh->root->point_index[1] = -1;
+                               bvh->root->point_index[2] = -1;
+                               bvh->root->point_index[3] = -1;
+                       }
+                       
+                       tree->isleaf = 1;
+                       tree->nextLeaf = NULL;
+                       tree->prevLeaf = bvh->leaf_tree;
+                       tree->parent = NULL;
+                       tree->count_nodes = 0;
+
+                       if(i==0)
+                       {
+                               bvh->leaf_tree = bvh->leaf_root = tree;
+                       }
+                       else
+                       {
+                               bvh->leaf_tree->nextLeaf = tree;
+                               bvh->leaf_tree = bvh->leaf_tree->nextLeaf;
+                       }               
+
+                       tree->nodes[0] = tree->nodes[1] = tree->nodes[2] = tree->nodes[3] = NULL;               
+
+                       bvh_calc_DOP_hull_static(bvh, &face_list[i], 1, tree->bv);
+
+                       // inflate the bv with some epsilon
+                       for (j = KDOP_START; j < KDOP_END; j++)
+                       {
+                               tree->bv[(2 * j)] -= bvh->epsilon; // minimum 
+                               tree->bv[(2 * j) + 1] += bvh->epsilon;  // maximum 
+                       }
+                       
+                       nlink = tnlink;
+               }
+               
+               // build root bvh
+               bvh_calc_DOP_hull_from_faces(bvh, face_list, bvh->numfaces, bvh->root->bv);
+
+               // This is the traversal function. 
+               bvh_div_env_node(bvh, bvh->root, face_list, 0, bvh->numfaces-1, 0, nlink);
+               if (face_list)
+                       MEM_freeN(face_list);
+               
+               // BLI_edgehash_free(edgehash, NULL);
+       }
+       
+
+       return bvh;
+}
+
+BVH *bvh_build_from_mvert (MFace *mfaces, unsigned int numfaces, MVert *x, unsigned int numverts, float epsilon)
+{
+       unsigned int i = 0, j = 0;
+       CollisionTree **face_list=NULL;
+       BVH     *bvh=NULL;
+       CollisionTree *tree=NULL;
+       LinkNode *nlink = NULL;
+       MFace *mface = NULL;
+       
+       bvh = MEM_callocN(sizeof(BVH), "BVH");
+       if (bvh == NULL) 
+       {
+               printf("bvh: Out of memory.\n");
+               return NULL;
+       }
+       
+       bvh->flags = 0;
+       bvh->leaf_tree = NULL;
+       bvh->leaf_root = NULL;
+       bvh->tree = NULL;
+
+       bvh->epsilon = epsilon;
+       bvh->numfaces = numfaces;
+       
+       // we have no faces, we save seperate points
+       if(!mfaces)
+       {
+               bvh->numfaces = numverts;
+       }
+
+       bvh->numverts = numverts;
+       bvh->xnew = MEM_dupallocN(x);   
+       bvh->x = MEM_dupallocN(x);      
+       tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
+       
+       if (tree == NULL) 
+       {
+               printf("bvh_build: Out of memory for nodes.\n");
+               bvh_free(bvh);
+               return NULL;
+       }
+       
+       BLI_linklist_append(&bvh->tree, tree);
+       
+       return bvh_build(bvh, mfaces, numfaces);
+}
+
+// bvh_overlap - is it possbile for 2 bv's to collide ?
+int bvh_overlap(float *bv1, float *bv2)
+{
+       int i = 0;
+       for (i = KDOP_START; i < KDOP_END; i++)
+       {
+               // Minimum test.
+               if (bv1[(2 * i)] > bv2[(2 * i) + 1]) 
+               {
+                       return 0;
+               }
+               // Maxiumum test.
+               if (bv2[(2 * i)] > bv1[(2 * i) + 1]) 
+               {
+                       return 0;
+               }
+       }
+       
+       return 1;
+}
+/**
+ * bvh_traverse - traverse two bvh trees looking for potential collisions.
+ *
+ * max collisions are n*n collisions --> every triangle collide with
+ * every other triangle that doesn't require any realloc, but uses
+ * much memory
+ */
+int bvh_traverse(CollisionTree *tree1, CollisionTree *tree2, LinkNode *collision_list)
+{
+       int i = 0, ret = 0;
+               
+       if (bvh_overlap(tree1->bv, tree2->bv)) 
+       {               
+               // Check if this node in the first tree is a leaf
+               if (tree1->isleaf) 
+               {
+                       // Check if this node in the second tree a leaf
+                       if (tree2->isleaf) 
+                       {
+                               // save potential colliding triangles
+                               CollisionPair *collpair = (CollisionPair *)MEM_callocN(sizeof(CollisionPair), "CollisionPair");
+                               
+                               VECCOPY(collpair->point_indexA, tree1->point_index);
+                               collpair->point_indexA[3] = tree1->point_index[3];
+                               
+                               VECCOPY(collpair->point_indexB, tree2->point_index);
+                               collpair->point_indexB[3] = tree2->point_index[3];
+                               
+                               BLI_linklist_append(&collision_list, collpair);
+                               
+                               return 1;
+                       }
+                       else 
+                       {
+                               // Process the quad tree.
+                               for (i = 0; i < 4; i++)
+                               {
+                                       // Only traverse nodes that exist.
+                                       if (tree2->nodes[i] && bvh_traverse (tree1, tree2->nodes[i], collision_list))
+                                               ret = 1;
+                               }
+                       }
+               }
+               else 
+               {
+                       // Process the quad tree.
+                       for (i = 0; i < 4; i++)
+                       {
+                               // Only traverse nodes that exist.
+                               if (tree1->nodes [i] && bvh_traverse (tree1->nodes[i], tree2, collision_list))
+                                       ret = 1;
+                       }
+               }
+       }
+
+       return ret;
+}
+
+// bottom up update of bvh tree:
+// join the 4 children here
+void bvh_join(CollisionTree *tree)
+{
+       int     i = 0, j = 0;
+       if (!tree)
+               return;
+       
+       for (i = 0; i < 4; i++)
+       {
+               if (tree->nodes[i]) 
+               {
+                       for (j = KDOP_START; j < KDOP_END; j++)
+                       {
+                               // update minimum 
+                               if ((tree->nodes[i]->bv[(2 * j)] < tree->bv[(2 * j)]) || (i == 0)) 
+                               {
+                                       tree->bv[(2 * j)] = tree->nodes[i]->bv[(2 * j)];
+                               }
+                               // update maximum 
+                               if ((tree->nodes[i]->bv[(2 * j) + 1] > tree->bv[(2 * j) + 1])|| (i == 0))
+                               {
+                                       tree->bv[(2 * j) + 1] = tree->nodes[i]->bv[(2 * j) + 1];
+                               }
+                       }
+               }
+               else
+                       break;
+       }
+}
+
+// update static bvh
+// needs new positions in bvh->x, bvh->xnew
+void bvh_update(BVH * bvh, int moving)
+{
+       TreeNode *leaf, *parent;
+       int traversecheck = 1;  // if this is zero we don't go further 
+       unsigned int j = 0;
+       
+       for (leaf = bvh->leaf_root; leaf; leaf = leaf->nextLeaf)
+       {
+               traversecheck = 1;
+               if ((leaf->parent) && (leaf->parent->traversed == leaf->parent->count_nodes)) 
+               {                       
+                       leaf->parent->traversed = 0;
+               }
+               if(!moving)
+                       bvh_calc_DOP_hull_static(bvh, &leaf, 1, leaf->bv);
+               else
+                       bvh_calc_DOP_hull_moving(bvh, &leaf, 1, leaf->bv);
+
+               // inflate the bv with some epsilon
+               for (j = KDOP_START; j < KDOP_END; j++)
+               {                       
+                       leaf->bv[(2 * j)] -= bvh->epsilon; // minimum 
+                       leaf->bv[(2 * j) + 1] += bvh->epsilon;  // maximum 
+               }
+
+               for (parent = leaf->parent; parent; parent = parent->parent)
+               {                       
+                       if (traversecheck) 
+                       {
+                               parent->traversed++;    // we tried to go up in hierarchy 
+                               if (parent->traversed < parent->count_nodes) 
+                               {
+                                       traversecheck = 0;
+
+                                       if (parent->parent) 
+                                       {
+                                               if (parent->parent->traversed == parent->parent->count_nodes) 
+                                               {
+                                                       parent->parent->traversed = 0;
+                                               }
+                                       }
+                                       break;  // we do not need to check further 
+                               }
+                               else 
+                               {
+                                       bvh_join(parent);
+                               }
+                       }
+
+               }
+       }       
+}
+
+void bvh_update_from_mvert(BVH * bvh, MVert *x, unsigned int numverts, MVert *xnew, int moving)
+{
+       if(!bvh)
+               return;
+       
+       if(numverts!=bvh->numverts)
+               return;
+       
+       if(x)
+               memcpy(bvh->x, x, sizeof(MVert) * numverts);
+       
+       if(xnew)
+               memcpy(bvh->xnew, xnew, sizeof(MVert) * numverts);
+       
+       bvh_update(bvh, moving);
+}
+
index 98ba46d49d561860418b4775bac57ecda51d9d57..4b65381c3b7a50e1e50e2daeeccabd3c55916a27 100644 (file)
@@ -51,6 +51,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "DNA_armature_types.h"
+#include "DNA_cloth_types.h"
 #include "DNA_effect_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
@@ -71,6 +72,7 @@
 #include "BKE_main.h"
 #include "BKE_anim.h"
 #include "BKE_bad_level_calls.h"
+#include "BKE_collisions.h"
 #include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_utildefines.h"
@@ -84,6 +86,7 @@
 #include "BKE_object.h"
 #include "BKE_mesh.h"
 #include "BKE_softbody.h"
+#include "BKE_cloth.h"
 #include "BKE_material.h"
 #include "depsgraph_private.h"
 
@@ -4855,6 +4858,246 @@ static void softbodyModifier_deformVerts(
        sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts);
 }
 
+
+/* Cloth */
+
+static void clothModifier_initData(ModifierData *md) 
+{
+       ClothModifierData *clmd = (ClothModifierData*) md;
+       cloth_init (clmd);
+}
+/*
+static void clothModifier_deformVerts(
+               ModifierData *md, Object *ob, DerivedMesh *derivedData,
+               float (*vertexCos)[3], int numVerts)
+{
+       DerivedMesh *dm = 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(dm)
+       {
+               CDDM_apply_vert_coords(dm, vertexCos);
+               CDDM_calc_normals(dm);
+       }
+       
+       clothModifier_do((ClothModifierData *)md, ob, dm, vertexCos, numVerts);
+       
+       if(dm)
+               dm->release(dm);
+}
+*/
+
+static DerivedMesh *clothModifier_applyModifier(
+               ModifierData *md, Object *ob, DerivedMesh *derivedData,
+  int useRenderParams, int isFinalCalc)
+{
+       DerivedMesh *result = NULL;
+       
+       ClothModifierData *clmd = (ClothModifierData*) md;
+
+       result = clothModifier_do(clmd, ob, derivedData);
+
+       CDDM_calc_normals(result);
+
+       return result;
+}
+
+static void clothModifier_updateDepgraph(
+                ModifierData *md, DagForest *forest, Object *ob,
+                DagNode *obNode)
+{
+       ClothModifierData *clmd = (ClothModifierData*) md;
+       
+       Base *base;
+       
+       if(clmd)
+       {
+               for(base = G.scene->base.first; base; base= base->next) 
+               {
+                       Object *ob1= base->object;
+                       if(ob1 != ob)
+                       {
+                               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);
+                                       }
+                               }
+                       }
+               }
+       }       
+}
+
+CustomDataMask clothModifier_requiredDataMask(ModifierData *md)
+{
+       ClothModifierData *clmd = (ClothModifierData *)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)
+                       dataMask |= (1 << CD_MDEFORMVERT);
+
+       return dataMask;
+}
+
+
+static int clothModifier_dependsOnTime(ModifierData *md)
+{
+       return 1;
+}
+
+static void clothModifier_freeData(ModifierData *md)
+{
+       ClothModifierData *clmd = (ClothModifierData*) md;
+       
+       if (clmd) 
+       {
+               clmd->sim_parms.flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT;
+               cloth_free_modifier (clmd);
+       }
+}
+
+/* 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->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);
+               
+               collmd->x = NULL;
+               collmd->xnew = NULL;
+               collmd->current_x = NULL;
+               collmd->current_xnew = 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->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);
+                       }
+                       
+                       collmd->time = current_time;
+               }
+       }
+       
+       if(dm)
+               dm->release(dm);
+}
+
 /* Boolean */
 
 static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
@@ -5139,6 +5382,32 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
                mti->flags = eModifierTypeFlag_AcceptsCVs
                             | eModifierTypeFlag_RequiresOriginalData;
                mti->deformVerts = softbodyModifier_deformVerts;
+       
+               mti = INIT_TYPE(Cloth);
+               mti->type = eModifierTypeType_Nonconstructive;
+               mti->initData = clothModifier_initData;
+               mti->flags = eModifierTypeFlag_AcceptsMesh
+                               | eModifierTypeFlag_RequiresOriginalData;
+                                       // | eModifierTypeFlag_SupportsMapping
+                                       // | eModifierTypeFlag_SupportsEditmode 
+                                       // | eModifierTypeFlag_EnableInEditmode;
+               mti->dependsOnTime = clothModifier_dependsOnTime;
+               mti->freeData = clothModifier_freeData; 
+               mti->requiredDataMask = clothModifier_requiredDataMask;
+               // mti->copyData = clothModifier_copyData;
+               // mti->deformVerts = clothModifier_deformVerts;
+               mti->applyModifier = clothModifier_applyModifier;
+               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;
@@ -5341,6 +5610,13 @@ int modifiers_isSoftbodyEnabled(Object *ob)
        return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
 }
 
+ClothModifierData *modifiers_isClothEnabled(Object *ob)
+{
+       ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+
+       return clmd;
+}
+
 LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask)
 {
        LinkNode *dataMasks = NULL;
index 2293fbef0b5e09dd481a6fad277872361e5e8d19..fe84ae570961ca91a594d9e6b6511bac13e65b2e 100644 (file)
@@ -60,6 +60,7 @@
 #include "DNA_actuator_types.h"
 #include "DNA_brush_types.h"
 #include "DNA_camera_types.h"
+#include "DNA_cloth_types.h"
 #include "DNA_color_types.h"
 #include "DNA_controller_types.h"
 #include "DNA_constraint_types.h"
 
 #include "BKE_action.h"
 #include "BKE_armature.h"
+#include "BKE_cloth.h"
 #include "BKE_colortools.h"
 #include "BKE_constraint.h"
 #include "BKE_curve.h"
@@ -2878,7 +2880,31 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                        SubsurfModifierData *smd = (SubsurfModifierData*) md;
 
                        smd->emCache = smd->mCache = 0;
-               } else if (md->type==eModifierType_Hook) {
+               } 
+               else if (md->type==eModifierType_Cloth) {
+                  ClothModifierData    *clmd = (ClothModifierData*) md;
+
+                  clmd->clothObject = NULL;
+                  clmd->sim_parms.cache = NULL;
+               
+                  if (clmd->sim_parms.cache) {
+                          // TODO 
+                         // clmd->cache = newdataadr (fd, clmd->cache);
+                         printf ("direct_link_modifiers: read cloth baked_data.\n");
+                  }
+               } 
+               else if (md->type==eModifierType_Collision) {
+                       CollisionModifierData *collmd = (CollisionModifierData*) md;
+                       
+                       collmd->x = NULL;
+                       collmd->xnew = NULL;
+                       collmd->current_x = NULL;
+                       collmd->current_xnew = NULL;
+                       collmd->time = -1;
+                       collmd->numverts = 0;
+                       collmd->tree = NULL;
+               }
+               else if (md->type==eModifierType_Hook) {
                        HookModifierData *hmd = (HookModifierData*) md;
 
                        hmd->indexar= newdataadr(fd, hmd->indexar);
@@ -2990,7 +3016,6 @@ static void direct_link_object(FileData *fd, Object *ob)
                sb->bpoint= NULL;       // init pointers so it gets rebuilt nicely
                sb->bspring= NULL;
                sb->scratch= NULL;
-
                
                sb->keys= newdataadr(fd, sb->keys);
                test_pointer_array(fd, (void **)&sb->keys);
index 45621c5fcd080c125ea7f284566c466bf0289d3b..ba4cbd1b9506e0abded49a6e160611ca7e230127 100644 (file)
@@ -107,6 +107,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi
 #include "DNA_actuator_types.h"
 #include "DNA_brush_types.h"
 #include "DNA_camera_types.h"
+#include "DNA_cloth_types.h"
 #include "DNA_color_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_controller_types.h"
@@ -154,6 +155,7 @@ Important to know is that 'streaming' has been added to files, for Blender Publi
 #include "BKE_action.h"
 #include "BKE_bad_level_calls.h" // build_seqar (from WHILE_SEQ) free_oops error
 #include "BKE_blender.h"
+#include "BKE_cloth.h"
 #include "BKE_curve.h"
 #include "BKE_customdata.h"
 #include "BKE_constraint.h"
@@ -769,6 +771,23 @@ static void write_constraint_channels(WriteData *wd, ListBase *chanbase)
 
 }
 
+/*
+// TODO: finish this
+static void write_cloth_cache(WriteData *wd, LinkNode *ln)
+{
+       
+       while(ln) {
+               writestruct(wd, DATA, "cloth_cache", 1, ln);            
+               writestruct(wd, DATA, "cloth_cache_frame", 1, ln->link);
+               writestruct(wd, DATA, "cloth_cache_frame_verts", 1, ln->link);
+               writestruct(wd, DATA, "cloth_cache_frame_springs", 1, ln->link);
+               }
+
+               ln = ln->next;
+       }
+}
+*/
+               
 static void write_modifiers(WriteData *wd, ListBase *modbase)
 {
        ModifierData *md;
@@ -784,6 +803,24 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
                        HookModifierData *hmd = (HookModifierData*) md;
                        
                        writedata(wd, DATA, sizeof(int)*hmd->totindex, hmd->indexar);
+       }
+       else if (md->type==eModifierType_Cloth) {
+                  int                                  n;
+                  ClothModifierData    *clmd = (ClothModifierData *) md;
+
+                  if (clmd->sim_parms.cache) {
+                         // Compute the number of vertices we're saving.
+                          // TODO
+                          // write_cloth_cache();
+                         /*
+                          // old code
+                         n = (clmd->sim_parms.bake_end_frame - clmd->sim_parms.bake_start_frame + 1) *
+                                clmd->sim_parms.bake_num_verts;
+                         writedata (wd, DATA, n *  sizeof (clmd->baked_data [0]), clmd->baked_data);
+                         printf ("write_modifiers: wrote %d elements of size %d for cloth baked data.\n",
+                                         n, sizeof (clmd->baked_data [0]));
+                          */
+                  }
                }
        }
 }
index fec85c03b77c94c253641e594f574a9abdfdb0b3..e492490fbaba71a3aec16198d16180dd09424435 100644 (file)
@@ -282,6 +282,14 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
 #define B_GROUP_RELINK                 1460
 #define B_OBJECT_IPOFLAG               1461
 
+
+/* Cloth sim button defines */
+#define B_CLOTH_CLEARCACHEALL          1470
+#define B_CLOTH_CLEARCACHEFRAME                1471
+#define B_CLOTH_CHANGEPREROLL                  1472
+#define B_CLOTH_DEL_VG                                 1473
+#define B_CLOTH_RENEW  1474
+
 /* *********************** */
 #define B_WORLDBUTS            1600
 
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
new file mode 100644 (file)
index 0000000..b4592e4
--- /dev/null
@@ -0,0 +1,169 @@
+/**
+* $Id: DNA_cloth_types.h,v 1.1 2007/08/01 02:28:34 daniel Exp $
+*
+* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version. The Blender
+* Foundation also sells licenses for use in proprietary software under
+* the Blender License.  See http://www.blender.org/BL/ for information
+* about this.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*
+* The Original Code is Copyright (C) 2006 by NaN Holding BV.
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): Daniel (Genscher), Todd Koeckeritz  (zaz)
+*
+* ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+#ifndef DNA_CLOTH_TYPES_H
+#define DNA_CLOTH_TYPES_H
+
+#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 */
+       int     preroll;        /* How many frames of simulation to do before we start. */
+       float   Cdis;           /* Mechanical damping of springs.               */
+       float   Cvi;            /* Viscous/fluid damping.                       */
+       int     stepsPerFrame;  /* Number of time steps per frame.                      */
+       float   gravity [3];    /* Gravity/external force vector.                       */
+       float   ufluid [3];     /* Velocity vector of the fluid.                */
+       float   dt;             /* This is the duration of our time step, computed.             */
+       float   mass;           /* The mass of the entire cloth.                */
+       float   structural;     /* Structural spring stiffness.                 */
+       float   shear;          /* Shear spring stiffness.                      */
+       float   bending;        /* Flexion spring stiffness.                    */
+       float   sim_time;
+       int     flags;          /* flags, see CSIMSETT_FLAGS enum above.        */
+       short   solver_type;    /* which solver should be used?                         */
+       short   pad2;
+       float   maxgoal;        /* see SB */
+       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;
+       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;
+
+
+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.          */
+       int     flags;                  /* collision flags defined in BKE_cloth.h */
+       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;
+       struct CollisionTree    *tree;          /* collision tree for this cloth object */
+       struct MFace            *mfaces;
+       struct Implicit_Data    *implicit;      /* our implicit solver connects to this pointer */
+       struct MVert            *x;
+       struct MVert            *xnew;
+       struct MVert            *current_x;
+       struct MVert            *current_xnew;
+}
+Cloth;
+
+#endif
index 71e850e4368292be98563872db72dfc706b55e3b..b25c3e7992187412fa6e708bb53c7cf4efd5474a 100644 (file)
@@ -9,6 +9,8 @@
 
 /* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! */
 
+#include "DNA_cloth_types.h"
+
 typedef enum ModifierType {
        eModifierType_None = 0,
        eModifierType_Subsurf,
@@ -28,6 +30,8 @@ typedef enum ModifierType {
        eModifierType_UVProject,
        eModifierType_Smooth,
        eModifierType_Cast,
+       eModifierType_Cloth,
+       eModifierType_Collision,
        NUM_MODIFIER_TYPES
 } ModifierType;
 
@@ -335,6 +339,27 @@ typedef struct SoftbodyModifierData {
        ModifierData modifier;
 } SoftbodyModifierData;
 
+typedef struct ClothModifierData {
+   ModifierData                modifier;
+       
+   Cloth               *clothObject;   /* The internal data structure for cloth.               */
+   SimulationSettings  sim_parms;      /* definition is in DNA_cloth_types.h                   */
+   CollisionSettings   coll_parms;     /* definition is in DNA_cloth_types.h                   */
+} ClothModifierData;
+
+typedef struct CollisionModifierData {
+       ModifierData            modifier;
+       
+       struct MVert *x; /* position at the beginning of the frame */
+       struct MVert *xnew; /* position at the end of the frame */
+       struct MVert *current_xnew; /* new position at the actual inter-frame step */
+       struct MVert *current_x; /* position at the actual inter-frame step */
+       
+       unsigned int numverts;
+       float time;
+       struct BVH *tree;       /* collision tree for this cloth object */
+} CollisionModifierData;
+
 typedef enum {
        eBooleanModifierOp_Intersect,
        eBooleanModifierOp_Union,
index a821e209ef0c3870031325d98a78cda9a66bab93..062989d07548d8d1fe54e87eef9ce791d35d9766 100644 (file)
@@ -113,7 +113,6 @@ typedef struct SoftBody {
                ;   
 
        struct SBScratch *scratch;      /* scratch pad/cache on live time not saved in file */
-
 } SoftBody;
 
 /* pd->forcefield:  Effector Fields types */
index af41380d5f8382106a022316c72aed20e68c11b8..41a8e8127f0d3ecc6cac5457ca9b67097e9cd5bd 100644 (file)
@@ -127,6 +127,7 @@ char *includefiles[] = {
        "DNA_color_types.h",
        "DNA_brush_types.h",
        "DNA_customdata_types.h",
+       "DNA_cloth_types.h",
        // if you add files here, please add them at the end
        // of makesdna.c (this file) as well
 
@@ -1146,4 +1147,5 @@ int main(int argc, char ** argv)
 #include "DNA_color_types.h"
 #include "DNA_brush_types.h"
 #include "DNA_customdata_types.h"
+#include "DNA_cloth_types.h"
 /* end of list */
index f779d4948951b87965465bf0d296ff85ac862407..c8ac0fc4b158b3ffd98907618fec99164f93a8e1 100644 (file)
@@ -951,6 +951,8 @@ static uiBlock *modifiers_add_menu(void *ob_v)
 
                /* Only allow adding through appropriate other interfaces */
                if(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue;
+               
+               if(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue;
 
                if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
                   (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
@@ -1483,7 +1485,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
        uiBlockSetCol(block, TH_AUTO);
        
        /* open/close icon */
-       if (!isVirtual) {
+       if (!isVirtual && md->type!=eModifierType_Collision) {
                uiBlockSetEmboss(block, UI_EMBOSSN);
                uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, B_MODIFIER_REDRAW, VICON_DISCLOSURE_TRI_RIGHT, x-10, y-2, 20, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier");
        }
@@ -1500,8 +1502,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                uiBlockBeginAlign(block);
                uiDefBut(block, TEX, B_MODIFIER_REDRAW, "", x+10, y-1, buttonWidth-60, 19, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); 
 
-                       /* Softbody not allowed in this situation, enforce! */
-               if (md->type!=eModifierType_Softbody || !(ob->pd && ob->pd->deflect)) {
+               /* Softbody not allowed in this situation, enforce! */
+               if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) {
                        uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering");
                        uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display");
                        if (mti->flags&eModifierTypeFlag_SupportsEditmode) {
@@ -1540,9 +1542,13 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                uiButSetFunc(but, modifiers_moveDown, ob, md);
                
                uiBlockSetEmboss(block, UI_EMBOSSN);
-
-               but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
-               uiButSetFunc(but, modifiers_del, ob, md);
+               
+               // deletion over the deflection panel
+               if(md->type!=eModifierType_Collision)
+               {
+                       but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier");
+                       uiButSetFunc(but, modifiers_del, ob, md);
+               }
                uiBlockSetCol(block, TH_AUTO);
        }
 
@@ -1601,6 +1607,10 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
                                height += 20;
                } else if (md->type==eModifierType_Softbody) {
                        height = 26;
+               } else if (md->type==eModifierType_Cloth) {
+                       height = 26;
+               } else if (md->type==eModifierType_Collision) {
+                       height = 19;
                } else if (md->type==eModifierType_Boolean) {
                        height = 48;
                } else if (md->type==eModifierType_Array) {
@@ -1612,11 +1622,11 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
 
                y -= 18;
 
-               if (!isVirtual) {
+               if (!isVirtual && (md->type!=eModifierType_Collision)) {
                        uiBlockBeginAlign(block);
                        but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Apply",  lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Apply the current modifier and remove from the stack");
                        uiButSetFunc(but, modifiers_applyModifier, ob, md);
-                       if (md->type!=eModifierType_Softbody) {
+                       if ((md->type!=eModifierType_Softbody) && (md->type!=eModifierType_Cloth)) {
                                but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy",   lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
                                uiButSetFunc(but, modifiers_copyModifier, ob, md);
                        }
@@ -3312,6 +3322,9 @@ void do_latticebuts(unsigned short event)
                        if(ob==G.obedit) resizelattice(editLatt, lt->opntsu, lt->opntsv, lt->opntsw, NULL);
                        else resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, NULL);
                        ob->softflag |= OB_SB_REDO;
+                       if(modifiers_isClothEnabled(ob)) {
+                               cloth_free_modifier(modifiers_isClothEnabled(ob));
+                       }
                        DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                        allqueue(REDRAWVIEW3D, 0);
                }
@@ -3320,6 +3333,9 @@ void do_latticebuts(unsigned short event)
                        lt = ob->data;
                        resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, ob);
                        ob->softflag |= OB_SB_REDO;
+                       if(modifiers_isClothEnabled(ob)) {
+                               cloth_free_modifier(modifiers_isClothEnabled(ob));
+                       }
                        DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
                        allqueue(REDRAWVIEW3D, 0);
                }
index 35db9294af1fdc2100e29d78a8234d30d9fc7f85..0754aa62016fb58f3a0e56f1a7af5fc38325c8ee 100644 (file)
@@ -86,6 +86,7 @@
 #include "DNA_action_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_camera_types.h"
+#include "DNA_cloth_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_effect_types.h"
 
 #include "BKE_anim.h"
 #include "BKE_armature.h"
+#include "BKE_cloth.h"
 #include "BKE_constraint.h"
 #include "BKE_curve.h"
 #include "BKE_deform.h"
@@ -825,19 +827,21 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                
                                /* Draw target parameters */
                                uiBlockBeginAlign(block);
-                                       uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
-                                       
-                                       if (is_armature_target(data->tar)) {
-                                               but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
-                                               uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
-                                       }
-                                       else if (is_geom_target(data->tar)) { 
-                                               but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
-                                               uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
-                                       }
-                                       else {
-                                               strcpy(data->subtarget, "");
-                                       }
+
+                               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
+                               
+                               if (is_armature_target(data->tar)) {
+                                       but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
+                                       uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
+                               }
+                               else if (is_geom_target(data->tar)) { 
+                                       but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
+                                       uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)data->tar);
+                               }
+                               else {
+                                       strcpy(data->subtarget, "");
+                               }
+
                                uiBlockEndAlign(block);
                                
                                /* Draw XYZ toggles */
@@ -880,7 +884,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                                strcpy(data->subtarget, "");
                                        }
                                uiBlockEndAlign(block);
-                               
+
                                /* Draw XYZ toggles */
                                uiBlockBeginAlign(block);
                                        uiDefButBitI(block, TOG, SIZELIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
@@ -904,7 +908,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                
                                /* IK Target */
                                uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
-                               
+
                                /* Draw target parameters */
                                uiBlockBeginAlign(block);
                                uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco, *yco-44, 137, 19, &data->tar, "Target Object"); 
@@ -2169,8 +2173,68 @@ void do_object_panels(unsigned short event)
        case B_OBJECT_IPOFLAG:
                if(ob->ipo) ob->ipo->showkey= (ob->ipoflag & OB_DRAWKEY)?1:0;
                allqueue(REDRAWVIEW3D, 0);
+       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_cache_free(clmd, 2); 
+                               allqueue(REDRAWBUTSOBJECT, 0);
+                               allqueue(REDRAWVIEW3D, 0);
+                       }       
+               }
+               break;  
+       case B_CLOTH_CLEARCACHEFRAME:
+               {
+                       ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+                       if(clmd)
+                       {
+                               cloth_cache_free(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); 
+                                       allqueue(REDRAWBUTSOBJECT, 0);
+                                       allqueue(REDRAWVIEW3D, 0);
+                               }
+                       }
+               }
+               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)
+                       {
+                               do_object_panels(B_CLOTH_CLEARCACHEALL);
+                               cloth_free_modifier (clmd);
+                       }
+               }
                break;
-               
        default:
                if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
                        int a=B_SELEFFECT;
@@ -2698,10 +2762,29 @@ void do_effects_panels(unsigned short event)
 
 }
 
+/* Panel for collision */
+static void object_collision__enabletoggle(void *ob_v, void *arg2)
+{
+       Object *ob = ob_v;
+       ModifierData *md = modifiers_findByType(ob, eModifierType_Collision);
+
+       if (!md) {
+               md = modifier_new(eModifierType_Collision);
+               BLI_addhead(&ob->modifiers, md);
+       }
+       else {
+               BLI_remlink(&ob->modifiers, md);
+               modifier_free(md);
+       }
+
+       allqueue(REDRAWBUTSEDIT, 0);
+}
+
 /* Panel for particle interaction settings */
 static void object_panel_fields(Object *ob)
 {
        uiBlock *block;
+       uiBut *but;
 
        block= uiNewBlock(&curarea->uiblocks, "object_panel_fields", UI_EMBOSS, UI_HELV, curarea->win);
        if(uiNewPanel(curarea, block, "Fields and Deflection", "Physics", 0, 0, 318, 204)==0) return;
@@ -2761,7 +2844,8 @@ static void object_panel_fields(Object *ob)
                        
                /* only meshes collide now */
                if(ob->type==OB_MESH) {
-                       uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
+                       but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection/Collision",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Make object collision object for dynamics");
+                       uiButSetFunc(but, object_collision__enabletoggle, ob, NULL);
                        if(pd->deflect) {
                                uiDefBut(block, LABEL, 0, "Particles",                  160,140,150,20, NULL, 0.0, 0, 0, 0, "");
                                
@@ -3032,6 +3116,233 @@ static void object_softbodies(Object *ob)
        uiBlockEndAlign(block);
 }
 
+/* Panel for cloth */
+static void object_cloth__enabletoggle(void *ob_v, void *arg2)
+{
+       Object *ob = ob_v;
+       ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
+
+       if (!md) {
+               md = modifier_new(eModifierType_Cloth);
+               BLI_addhead(&ob->modifiers, md);
+       }
+       else {
+               BLI_remlink(&ob->modifiers, md);
+               modifier_free(md);
+       }
+
+       allqueue(REDRAWBUTSEDIT, 0);
+}
+
+static void object_panel_cloth(Object *ob)
+{
+       uiBlock *block;
+       static int val, val2;
+       uiBut *but;
+       ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+       block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth", UI_EMBOSS, UI_HELV, curarea->win);
+       if(uiNewPanel(curarea, block, "Cloth", "Physics", 640, 0, 318, 204)==0) return;
+
+       if(ob->id.lib) uiSetButLock(1, "Can't edit library data");
+       val = ((clmd)?(1):(0));
+
+       but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Cloth Object",   10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become cloth");
+       uiButSetFunc(but, object_cloth__enabletoggle, ob, NULL);
+       uiDefBut(block, LABEL, 0, "",10,10,300,0, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/
+       
+       if(clmd)
+       {
+               // but = uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_COLLOBJ, B_EFFECT_DEP, "Collision Object",     170,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object");
+
+               if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ))
+               {
+                       Cloth *cloth = clmd->clothObject;
+                       int defCount;
+                       char *clvg1, *clvg2;
+                       char clmvg [] = "Mass Vertex Group%t|None%x0|";
+       
+                       val2=0;
+       
+       //              uiDefButBitI(block, TOG, CSIMSETT_FLAG_ADVANCED, REDRAWBUTSOBJECT, "Advanced",  180,200,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Enable advanced mode");
+                       
+                       /* GENERAL STUFF */
+                       uiClearButLock();
+                       uiBlockBeginAlign(block);
+                       uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:",       10,170,150,20, &clmd->sim_parms.structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure");
+                       uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:",         160,170,150,20, &clmd->sim_parms.bending, 0.0, 10000.0, 1000, 0, "Wrinkle possibility");
+                       uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:",  10,150,150,20, &clmd->sim_parms.stepsPerFrame, 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");
+                       uiBlockEndAlign(block);                 
+                       
+                       uiClearButLock();
+                       
+                       uiBlockBeginAlign(block);
+                       uiDefBut(block, LABEL, 0, "Gravity:",  10,100,60,20, NULL, 0.0, 0, 0, 0, "");
+                       // uiClearButLock();
+                       
+                       uiDefButF(block, NUM, B_CLOTH_RENEW, "X:",         70,100,80,20, &clmd->sim_parms.gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement");
+                       uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:",         150,100,80,20, &clmd->sim_parms.gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement");
+                       uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:",         230,100,80,20, &clmd->sim_parms.gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement");
+                       uiBlockEndAlign(block);
+                       
+                       /* GOAL STUFF */
+                       uiBlockBeginAlign(block);
+                       uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, REDRAWVIEW3D, "Use Goal", 10,70,130,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position");
+                       if (clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_GOAL)
+                       {
+                               if(ob->type==OB_MESH) 
+                               {
+                                       
+                                       defCount = sizeof (clmvg);
+                                       clvg1 = get_vertexgroup_menustr (ob);
+                                       clvg2 = MEM_callocN (strlen (clvg1) + 1 + defCount, "clothVgMS");
+                                       if (! clvg2) {
+                                               printf ("draw_modifier: error allocating memory for cloth vertex group menu string.\n");
+                                               return;
+                                       }
+                                       defCount = BLI_countlist (&ob->defbase);
+                                       if (defCount == 0) 
+                                       {
+                                               clmd->sim_parms.vgroup_mass = 0;
+                                       }
+                                       sprintf (clvg2, "%s%s", clmvg, clvg1);
+                                       
+                                       uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2,    140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups");      
+                                       MEM_freeN (clvg1);
+                                       MEM_freeN (clvg2);
+                                       
+                                       if(clmd->sim_parms.vgroup_mass) 
+                                       {
+                                               bDeformGroup *defGroup = BLI_findlink(&ob->defbase, clmd->sim_parms.vgroup_mass-1);
+                                               if(defGroup)
+                                                       uiDefBut(block, BUT, B_DIFF, defGroup->name,    160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group");
+                                               else
+                                                       uiDefBut(block, BUT, B_DIFF, "(no group)",      160,70,130,20, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore");
+                                               
+                                               uiDefIconBut(block, BUT, B_CLOTH_DEL_VG, ICON_X, 290,70,20,20, 0, 0, 0, 0, 0, "Disable use of vertex group");
+                                               
+                                       }
+                                       else
+                                               uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:",   160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used");
+                               
+                               }
+                               else 
+                               {
+                                       uiDefButS(block, TOG, B_CLOTH_RENEW, "W",                       140,70,20,20, &clmd->sim_parms.vgroup_mass, 0, 1, 0, 0, "Use control point weight values");
+                                       uiDefButF(block, NUM, B_CLOTH_RENEW, "Goal:",   160,70,150,20, &clmd->sim_parms.defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used");
+                               }
+                               
+                               uiDefButF(block, NUM, B_CLOTH_RENEW, "G Stiff:",        10,50,150,20, &clmd->sim_parms.goalspring, 0.0, 500.0, 10, 0, "Goal (vertex target position) spring stiffness");
+                               uiDefButF(block, NUM, B_CLOTH_RENEW, "G Damp:", 160,50,150,20, &clmd->sim_parms.goalfrict  , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction");
+                               uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:",          10,30,150,20, &clmd->sim_parms.mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range");
+                               uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:",          160,30,150,20, &clmd->sim_parms.maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range");
+                       }
+                       uiBlockEndAlign(block); 
+                       
+                       /*
+                       // no tearing supported anymore since modifier stack restrictions 
+                       uiBlockBeginAlign(block);
+                       uiDefButBitI(block, TOG, CSIMSETT_FLAG_TEARING_ENABLED, B_EFFECT_DEP, "Tearing",        10,0,150,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Sets object to become a cloth collision object");
+                       
+                       if (clmd->sim_parms.flags & CSIMSETT_FLAG_TEARING_ENABLED)
+                       {
+                               uiDefButI(block, NUM, B_DIFF, "Max extent:",       160,0,150,20, &clmd->sim_parms.maxspringlen, 1.0, 1000.0, 10, 0, "Maximum extension before spring gets cut");
+                       }
+                       
+                       uiBlockEndAlign(block); 
+                       */
+               }
+       }
+}
+
+
+static void object_panel_cloth_II(Object *ob)
+{
+       uiBlock *block;
+       static int val;
+       uiBut *but;
+       ClothModifierData *clmd = NULL;
+       
+       clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+       if(clmd)
+       {
+               if (!(clmd->sim_parms.flags & CLOTH_SIMSETTINGS_FLAG_COLLOBJ))
+               {
+                       Cloth *cloth = clmd->clothObject;
+                       char str[128];
+                       
+                       block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_II", UI_EMBOSS, UI_HELV, curarea->win);
+                       uiNewPanelTabbed("Cloth", "Physics");
+                       if(uiNewPanel(curarea, block, "Cloth Cache", "Physics", 651, 0, 318, 204)==0) return;
+               
+                       uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+                       
+                       uiDefButI(block, NUM, B_DIFF, "First Frame:",           10,160,150,20, &clmd->sim_parms.firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts");
+                       uiDefButI(block, NUM, B_DIFF, "Last Frame:",            160,160,150,20, &clmd->sim_parms.lastframe, 0, MAXFRAME, 10, 0, "Frame on which the simulation stops");
+
+                       if(clmd->sim_parms.cache)
+                       {
+                               int length = BLI_linklist_length(clmd->sim_parms.cache);
+                               
+                               /* correct spelling if only 1 frame cacheed --> only gimmick  */
+                               if(length-clmd->sim_parms.preroll>1)
+                                       sprintf (str, "Frame 1 - %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length);
+                               else
+                                       sprintf (str, "Frame %d cached. [%d in preroll, %d in total]", length-clmd->sim_parms.preroll, clmd->sim_parms.preroll, length);
+                               
+                               uiDefBut(block, LABEL, 0, str,  10,140,290,20, NULL, 0.0, 0, 0, 0, "");
+                               uiDefBut(block, LABEL, 0, "Clear cache:",  10,120,290,20, NULL, 0.0, 0, 0, 0, "");
+                               uiBlockBeginAlign (block);
+                               uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 10, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache without preroll");
+                               uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 155, 100,145,20, NULL, 0.0, 0.0, 0, 0, "Free cloth cache");    
+                               if(length>1) // B_CLOTH_CHANGEPREROLL
+                                       uiDefButI(block, NUM, B_CLOTH_CHANGEPREROLL, "Preroll:", 10,80,145,20, &clmd->sim_parms.preroll, 0, length-1, 1, 0, "Simulation starts on this frame"); 
+                               else
+                                       uiDefBut(block, LABEL, 0, " ",  10,80,145,20, NULL, 0.0, 0, 0, 0, "");
+                       }
+                       else
+                       {
+                               uiDefBut(block, LABEL, 0, "No frames cached.",  10,120,290,20, NULL, 0.0, 0, 0, 0, "");
+                       }
+                       uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache",  10,50,145,20, &clmd->sim_parms.flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed");
+                       uiBlockEndAlign(block);
+               }
+       }
+       // uiBlockEndAlign(block);
+}
+
+static void object_panel_cloth_III(Object *ob)
+{
+       uiBlock *block;
+       ClothModifierData *clmd = NULL;
+       
+       clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
+       if(clmd)
+       {       
+               block= uiNewBlock(&curarea->uiblocks, "object_panel_cloth_III", UI_EMBOSS, UI_HELV, curarea->win);
+               uiNewPanelTabbed("Cloth", "Physics");
+               if(uiNewPanel(curarea, block, "Cloth Collisions", "Physics", 651, 0, 318, 204)==0) return;
+       
+               uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
+               
+               uiBlockBeginAlign(block);
+               uiDefButBitI(block, TOG, CLOTH_COLLISIONSETTINGS_FLAG_ENABLED, REDRAWVIEW3D, "Enable collisions",       10,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);
+       }
+}
+
+
 static void object_panel_particles_motion(Object *ob)
 {
        uiBlock *block;
@@ -3535,6 +3846,9 @@ void physics_panels()
                object_panel_particles_motion(ob);
                object_softbodies(ob);
                object_softbodies_II(ob);
+               object_panel_cloth(ob);
+               object_panel_cloth_II(ob);
+               object_panel_cloth_III(ob);
                object_panel_fluidsim(ob);
        }
 }
index 15f4e65249005f74553ae731089a81f6f9f18577..e8514cee2df9abcbc70dadb7f67101abb777e184 100644 (file)
@@ -65,6 +65,7 @@
 
 #include "BKE_DerivedMesh.h"
 #include "BKE_depsgraph.h"
+#include "BKE_cloth.h"
 #include "BKE_customdata.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
@@ -72,6 +73,7 @@
 #include "BKE_main.h"
 #include "BKE_material.h"
 #include "BKE_mesh.h"
+#include "BKE_modifier.h"
 #include "BKE_object.h"
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
@@ -1324,7 +1326,11 @@ void load_editMesh(void)
        if(me->id.us>1) {
                Base *base;
                for(base= G.scene->base.first; base; base= base->next) {
-                       if(base->object->data==me) {
+                       if(base->object->data==me) {                            
+                               if(modifiers_isClothEnabled(base->object)) {
+                                       cloth_free_modifier(modifiers_isClothEnabled(base->object));
+                               }
+                               
                                base->object->softflag |= OB_SB_REDO;
                                base->object->recalc |= OB_RECALC_DATA;
                        }
index 997593b30b1ee515f4262fd83603b3e0223286f4..628d1c3b405636a0c9f77d1708bc1360695743de 100644 (file)
@@ -99,6 +99,7 @@
 #include "BKE_customdata.h"
 #include "BKE_blender.h"
 #include "BKE_booleanops.h"
+#include "BKE_cloth.h"
 #include "BKE_curve.h"
 #include "BKE_displist.h"
 #include "BKE_depsgraph.h"
@@ -1745,6 +1746,10 @@ void exit_editmode(int flag)     /* freedata==0 at render, 1= freedata, 2= do undo b
                sbObjectToSoftbody(ob);
        }
        
+       if(modifiers_isClothEnabled(ob)) {
+               cloth_free_modifier(modifiers_isClothEnabled(ob));
+       }
+       
        if(ob->type==OB_MESH && get_mesh(ob)->mr)
                multires_edge_level_update(ob, get_mesh(ob));
        
index 3e1f08c82a3ba3162dc09591f5af9229265945ae..7c4307a2eac9720c5e86bfc3df45a1e586a594b4 100644 (file)
@@ -76,6 +76,7 @@
 #include "BKE_action.h"
 #include "BKE_armature.h"
 #include "BKE_blender.h"
+#include "BKE_cloth.h"
 #include "BKE_curve.h"
 #include "BKE_constraint.h"
 #include "BKE_depsgraph.h"
@@ -2847,13 +2848,15 @@ void special_aftertrans_update(TransInfo *t)
        }
        else {
                base= FIRSTBASE;
-               while(base) {   
-                       
+               while(base) {                                           
                        if(base->flag & BA_DO_IPO) redrawipo= 1;
                        
                        ob= base->object;
                        
                        if(modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO;
+                       else if(modifiers_isClothEnabled(ob)) {
+                               cloth_free_modifier(modifiers_isClothEnabled(ob));
+                       }
                        
                        /* Set autokey if necessary */
                        if ((!cancelled) && (t->mode != TFM_DUMMY) && (base->flag & SELECT)) {
index 744933088c82461312191252d761895fd6b820d5..9f45bd7aaa06b74408422328cba3c8d7a7b0e6fe 100644 (file)
@@ -72,6 +72,7 @@
 #include "BKE_action.h"
 #include "BKE_anim.h"
 #include "BKE_armature.h"
+#include "BKE_cloth.h"
 #include "BKE_curve.h"
 #include "BKE_depsgraph.h"
 #include "BKE_displist.h"
@@ -419,8 +420,16 @@ void recalcData(TransInfo *t)
                        /* bah, softbody exception... recalcdata doesnt reset */
                        for(base= FIRSTBASE; base; base= base->next) {
                                if(base->object->recalc & OB_RECALC_DATA)
+                               {                                       
+                                       ClothModifierData *clmd = NULL;
+                                       
                                        if(modifiers_isSoftbodyEnabled(base->object)) {
                                                base->object->softflag |= OB_SB_REDO;
+                                       }
+                                       else if((clmd = (ClothModifierData *)modifiers_isClothEnabled(ob))) {
+                                               cloth_free_modifier(clmd);
+                                       }
+                                       
                                }
                        }
                }
@@ -453,10 +462,17 @@ void recalcData(TransInfo *t)
                                }                               
                        }
                        
-                       /* softbody exception */
-                       if(modifiers_isSoftbodyEnabled(ob)) {
-                               if(ob->recalc & OB_RECALC_DATA)
-                                       ob->softflag |= OB_SB_REDO;
+                       /* softbody & cloth exception */
+                       if(ob->recalc & OB_RECALC_DATA)
+                       {
+                               ClothModifierData *clmd = NULL;
+                               
+                               if(modifiers_isSoftbodyEnabled(ob)) {
+                                               ob->softflag |= OB_SB_REDO;
+                               }
+                               else if((clmd = (ClothModifierData *)modifiers_isClothEnabled(ob))) {
+                                       cloth_free_modifier(clmd);
+                               }
                        }
                        
                        /* proxy exception */
index 2f82cd2e2b2a758c1ba0f2d5b1eb0f955ee9ba4a..102aa79d47eefaaa79f6419c30d2fceef169754a 100644 (file)
@@ -64,6 +64,7 @@
 
 #include "BKE_armature.h"
 #include "BKE_DerivedMesh.h"
+#include "BKE_cloth.h"
 #include "BKE_customdata.h"
 #include "BKE_depsgraph.h"
 #include "BKE_deform.h"
@@ -1346,6 +1347,11 @@ void weight_paint(void)
        /* this flag is event for softbody to refresh weightpaint values */
        if(ob->soft) ob->softflag |= OB_SB_REDO;
        
+       // same goes for cloth
+       if(modifiers_isClothEnabled(ob)) {
+               cloth_free_modifier(modifiers_isClothEnabled(ob));
+       }       
+       
        BIF_undo_push("Weight Paint");
        allqueue(REDRAWVIEW3D, 0);
 }
index eb8f844df4d15929f683c90390ba3d68efdd849b..1b91a3343dcbc7dc1f9543fead7cb5cf62605bc4 100755 (executable)
@@ -55,8 +55,9 @@ def validate_arguments(args, bc):
             'BF_VERSE_INCLUDE',
             'VERSE_BUILD_BINARY', 'VERSE_BUILD_DIR', 'VERSE_REGEN_PROTO',
             'BF_TWEAK_MODE',
-            'WITHOUT_BF_INSTALL'
-            ]
+            'WITHOUT_BF_INSTALL',
+            'WITH_BF_OPENMP'
+           ]
 
     arg_list = ['BF_DEBUG', 'BF_QUIET', 'BF_CROSS', 'BF_UPDATE',
             'BF_INSTALLDIR', 'BF_TOOLSET', 'BF_BINNAME',
@@ -247,6 +248,8 @@ def read_opts(cfg, args):
         ('BF_FREETYPE_LIB', 'Freetype library', ''),
         ('BF_FREETYPE_LIBPATH', 'Freetype library path', ''),
 
+       (BoolOption('WITH_BF_OPENMP', 'Use OpenMP if true', 'false')),
+
         (BoolOption('WITH_BF_QUICKTIME', 'Use QuickTime if true', 'false')),
         ('BF_QUICKTIME', 'QuickTime base path', ''),
         ('BF_QUICKTIME_INC', 'QuickTime include path', ''),