Initial commit of cloth modifier from branch rev 13453

This commit is contained in:
Daniel Genrich 2008-01-29 21:01:12 +00:00
parent 3a3fe8a480
commit 77685023ca
36 changed files with 7447 additions and 48 deletions

@ -65,8 +65,9 @@ OPTION(WITH_ELBEEM "Enable Elbeem (Fluid Simulation)" ON)
OPTION(WITH_QUICKTIME "Enable Quicktime Support" OFF)
OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" OFF)
OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF)
OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON)
OPTION(YESIAMSTUPID "Enable execution on 64-bit platforms" OFF)
OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON)
OPTION(YESIAMSTUPID "Enable execution on 64-bit platforms" OFF)
OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF)
IF(NOT WITH_GAMEENGINE AND WITH_PLAYER)
MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE")
@ -184,6 +185,13 @@ IF(UNIX)
SET(LLIBS "-lXi -lutil -lc -lm -lpthread -lstdc++")
IF(WITH_OPENMP)
SET(LLIBS "${LLIBS} -lgomp ")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ")
ENDIF(WITH_OPENMP)
SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing -DXP_UNIX -Wno-char-subscripts")
SET(PLATFORM_LINKFLAGS "-pthread")
@ -270,6 +278,11 @@ IF(WIN32)
SET(CMAKE_C_FLAGS_MINSIZEREL "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O1 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /J" CACHE STRING "MSVC MT flags " FORCE)
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "/D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_DEPRECATE /D_SCL_SECURE_NO_DEPRECATE /wd4800 /wd4244 /wd4305 /O2 /Ob1 /DNDEBUG /EHsc /MT /W3 /nologo /Zi /J" CACHE STRING "MSVC MT flags " FORCE)
IF(WITH_OPENMP)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /openmp ")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp ")
ENDIF(WITH_OPENMP)
SET(SDL ${LIBDIR}/sdl)
SET(SDL_INC ${SDL}/include)
SET(SDL_LIB SDL)
@ -347,6 +360,12 @@ IF(APPLE)
SET(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
SET(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime")
IF(WITH_OPENMP)
SET(LLIBS "${LLIBS} -lgomp ")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ")
ENDIF(WITH_OPENMP)
SET(SDL ${LIBDIR}/sdl)
SET(SDL_INC ${SDL}/include)
SET(SDL_LIB SDL)

@ -179,6 +179,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'):

5
extern/SConscript vendored

@ -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'])

37
extern/bullet2/src/Bullet-C-Api.h vendored Normal file

@ -0,0 +1,37 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's.
Work in progress, functionality will be added on demand.
If possible, use the richer Bullet C++ API, by including "btBulletDynamicsCommon.h"
*/
#ifndef BULLET_C_API_H
#define BULLET_C_API_H
#ifdef __cplusplus
extern "C" {
#endif
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
#endif //BULLET_C_API_H

@ -13,6 +13,7 @@ ADD_LIBRARY(LibBulletDynamics
ConstraintSolver/btTypedConstraint.cpp
Dynamics/btDiscreteDynamicsWorld.cpp
Dynamics/btSimpleDynamicsWorld.cpp
Dynamics/Bullet-C-API.cpp
Dynamics/btRigidBody.cpp
Vehicle/btRaycastVehicle.cpp
Vehicle/btWheelInfo.cpp

@ -0,0 +1,115 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's.
Work in progress, functionality will be added on demand.
If possible, use the richer Bullet C++ API, by including <src/btBulletDynamicsCommon.h>
*/
#include "Bullet-C-Api.h"
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btAlignedAllocator.h"
#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;
}

@ -34,6 +34,7 @@ bulletdyn_src = ["BulletDynamics/ConstraintSolver/btContactConstraint.cpp",
"BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp",
"BulletDynamics/Dynamics/btRigidBody.cpp",
"BulletDynamics/Vehicle/btRaycastVehicle.cpp",
"BulletDynamics/Dynamics/Bullet-C-API.cpp",
"BulletDynamics/Vehicle/btWheelInfo.cpp"]
collision_src = ["BulletCollision/BroadphaseCollision/btAxisSweep3.cpp",
"BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp",

@ -36,5 +36,9 @@ IF(WINDOWS)
ADD_DEFINITIONS(-DUSE_MSVC6FIXES)
ENDIF(WINDOWS)
IF(WITH_OPENMP)
ADD_DEFINITIONS(-DPARALLEL)
ENDIF(WITH_OPENMP)
BLENDERLIB_NOLIST(bf_elbeem "${SRC}" "${INC}")
#, libtype='blender', priority=0 )

@ -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']

@ -22,6 +22,10 @@
#define round(x) (x)
#endif
#if PARALLEL==1
#include <omp.h>
#endif
/******************************************************************************
* Constructor
*****************************************************************************/
@ -160,13 +164,6 @@ void IsoSurface::triangulate( void )
mpEdgeVerticesZ[i] = -1;
}
ntlVec3Gfx pos[8];
float value[8];
int cubeIndex; // index entry of the cube
int triIndices[12]; // vertex indices
int *eVert[12];
IsoLevelVertex ilv;
// edges between which points?
const int mcEdges[24] = {
0,1, 1,2, 2,3, 3,0,
@ -193,7 +190,12 @@ void IsoSurface::triangulate( void )
px = mStart[0]-gsx*0.5;
for(int i=1;i<(mSizex-2);i++) {
px += gsx;
int cubeIndex; // index entry of the cube
float value[8];
int triIndices[12]; // vertex indices
int *eVert[12];
IsoLevelVertex ilv;
value[0] = *getData(i ,j ,k );
value[1] = *getData(i+1,j ,k );
value[2] = *getData(i+1,j+1,k );
@ -239,6 +241,7 @@ void IsoSurface::triangulate( void )
eVert[11] = &mpEdgeVerticesZ[ ISOLEVEL_INDEX( i+0, j+1, edgek+0) ];
// grid positions
ntlVec3Gfx pos[8];
pos[0] = ntlVec3Gfx(px ,py ,pz);
pos[1] = ntlVec3Gfx(px+gsx,py ,pz);
pos[2] = ntlVec3Gfx(px+gsx,py+gsy,pz);
@ -344,10 +347,7 @@ void IsoSurface::triangulate( void )
if(mUseFullEdgeArrays) {
errMsg("IsoSurface::triangulate","Disabling mUseFullEdgeArrays!");
}
// subdiv local arrays
gfxReal orgval[8];
gfxReal subdAr[2][11][11]; // max 10 subdivs!
ParticleObject* *arppnt = new ParticleObject*[mSizez*mSizey*mSizex];
// construct pointers
@ -408,13 +408,25 @@ void IsoSurface::triangulate( void )
debMsgStd("IsoSurface::triangulate",DM_MSG,"Starting. Parts in use:"<<pInUse<<", Subdivs:"<<mSubdivs, 9);
pz = mStart[2]-(double)(0.*gsz)-0.5*orgGsz;
for(int ok=1;ok<(mSizez-2)*mSubdivs;ok++) {
pz += gsz;
const int k = ok/mSubdivs;
if(k<=0) continue; // skip zero plane
#if PARALLEL==1
#pragma omp parallel for
#endif
for(int j=1;j<(mSizey-2);j++) {
for(int i=1;i<(mSizex-2);i++) {
float value[8];
ntlVec3Gfx pos[8];
int cubeIndex; // index entry of the cube
int triIndices[12]; // vertex indices
int *eVert[12];
IsoLevelVertex ilv;
gfxReal orgval[8];
gfxReal subdAr[2][11][11]; // max 10 subdivs!
orgval[0] = *getData(i ,j ,k );
orgval[1] = *getData(i+1,j ,k );
orgval[2] = *getData(i+1,j+1,k ); // with subdivs
@ -426,6 +438,7 @@ void IsoSurface::triangulate( void )
// prebuild subsampled array slice
const int sdkOffset = ok-k*mSubdivs;
for(int sdk=0; sdk<2; sdk++)
for(int sdj=0; sdj<mSubdivs+1; sdj++)
for(int sdi=0; sdi<mSubdivs+1; sdi++) {
@ -580,8 +593,13 @@ void IsoSurface::triangulate( void )
// init isolevel vertex
ilv.v = p1 + (p2-p1)*mu; // with subdivs
#if PARALLEL==1
#pragma omp critical
#endif
{
mPoints.push_back( ilv );
triIndices[e] = (mPoints.size()-1);
}
// store vertex
*eVert[ e ] = triIndices[e];
} else {
@ -591,23 +609,27 @@ void IsoSurface::triangulate( void )
} // along all edges
}
// removed cutoff treatment...
// Create the triangles...
#if PARALLEL==1
#pragma omp critical
#endif
{
for(int e=0; mcTriTable[cubeIndex][e]!=-1; e+=3) {
mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+0] ] );
mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+1] ] ); // with subdivs
mIndices.push_back( triIndices[ mcTriTable[cubeIndex][e+2] ] );
//errMsg("TTT"," i1"<<mIndices[mIndices.size()-3]<<" "<< " i2"<<mIndices[mIndices.size()-2]<<" "<< " i3"<<mIndices[mIndices.size()-1]<<" "<< mIndices.size() );
}
} // triangles in edge table?
}
}
}//si
}// sj
}//i
}// j
// copy edge arrays
for(int j=0;j<(mSizey-0)*mSubdivs;j++)
for(int i=0;i<(mSizex-0)*mSubdivs;i++) {

@ -151,9 +151,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

@ -0,0 +1,256 @@
/**
* 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 "float.h"
#include "BLI_linklist.h"
#include "BKE_collision.h"
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "DNA_cloth_types.h"
#include "DNA_customdata_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
struct Object;
struct Cloth;
struct MFace;
struct DerivedMesh;
struct ClothModifierData;
struct CollisionTree;
// this is needed for inlining behaviour
#ifndef _WIN32
#define LINUX
#define DO_INLINE inline
#else
#define DO_INLINE
#endif
#define CLOTH_MAX_THREAD 2
/**
* The definition of a cloth vertex.
*/
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 */
float avg_spring_len; /* average length of connected springs, UNUSED ATM */
float struct_stiff;
float bend_stiff;
float shear_stiff;
}
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];
float stiffness; /* stiffness factor from the vertex groups */
}
ClothSpring;
/* 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 FLT_EPSILON
// 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_FLAG_EDITMODE = ( 1 << 6 ), // are we in editmode? -several things disabled
CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE = (1 << 7), /* force cache freeing */
CLOTH_SIMSETTINGS_FLAG_SCALING = (1 << 8), /* is advanced scaling active? */
CLOTH_SIMSETTINGS_FLAG_LOADED = (1 << 9), /* did we just got load? */
} CLOTH_SIMSETTINGS_FLAGS;
/* COLLISION FLAGS */
typedef enum
{
CLOTH_COLLSETTINGS_FLAG_ENABLED = ( 1 << 1 ), /* enables cloth - object collisions */
CLOTH_COLLSETTINGS_FLAG_SELF = ( 1 << 2 ), /* unused */
} 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 CLOTH_VERT_FLAG_PINNED 1
#define CLOTH_VERT_FLAG_COLLISION 2
typedef void ( *CM_COLLISION_RESPONSE ) ( ClothModifierData *clmd, CollisionModifierData *collmd, CollisionTree *tree1, CollisionTree *tree2 );
/////////////////////////////////////////////////
// collision.c
////////////////////////////////////////////////
// needed for implicit.c
void bvh_collision_response ( ClothModifierData *clmd, ClothModifierData *coll_clmd, CollisionTree * tree1, CollisionTree * tree2 );
int cloth_bvh_objcollision ( ClothModifierData * clmd, float step, float dt );
int bvh_traverse ( ClothModifierData * clmd, CollisionModifierData * collmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response );
////////////////////////////////////////////////
////////////////////////////////////////////////
// implicit.c
////////////////////////////////////////////////
// needed for cloth.c
int implicit_init ( Object *ob, ClothModifierData *clmd );
int implicit_free ( ClothModifierData *clmd );
int implicit_solver ( Object *ob, float frame, ClothModifierData *clmd, ListBase *effectors );
void implicit_set_positions ( ClothModifierData *clmd );
////////////////////////////////////////////////
/////////////////////////////////////////////////
// cloth.c
////////////////////////////////////////////////
// needed for modifier.c
void cloth_free_modifier_extern (ClothModifierData *clmd);
void cloth_free_modifier (Object *ob, ClothModifierData *clmd);
void cloth_init (ClothModifierData *clmd);
DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc);
void cloth_update_normals (ClothVertex *verts, int nVerts, MFace *face, int totface);
// needed for collision.c
void bvh_update_from_cloth(ClothModifierData *clmd, int moving);
// needed for editmesh.c
void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr);
int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr);
// needed for button_object.c
void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr);
////////////////////////////////////////////////
/* 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;
/* 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;
#endif

@ -0,0 +1,176 @@
/**
* 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 "float.h"
#include <stdlib.h>
#include <string.h>
/* types */
#include "BLI_linklist.h"
#include "BKE_collision.h"
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "DNA_cloth_types.h"
#include "DNA_customdata_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
struct Object;
struct Cloth;
struct MFace;
struct DerivedMesh;
struct ClothModifierData;
struct CollisionTree;
////////////////////////////////////////
// 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
unsigned int tri_index; // this saves the index of the face
// 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 BVH
{
unsigned int numfaces;
unsigned int numverts;
MVert *current_x; // e.g. txold in clothvertex
MVert *current_xold; // e.g. tx in clothvertex
MFace *mfaces; // just a pointer to the original datastructure
struct LinkNode *tree;
CollisionTree *root; // TODO: saving the root --> is this really needed? YES!
CollisionTree *leaf_tree; /* Tail of the leaf linked list. */
CollisionTree *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
////////////////////////////////////////
/* 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;
////////////////////////////////////////
/////////////////////////////////////////////////
// forward declarations
/////////////////////////////////////////////////
// NOTICE: mvert-routines for building + update the BVH are the most native ones
// builds bounding volume hierarchy
void bvh_build (BVH *bvh);
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
// 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);
void bvh_update(BVH * bvh, 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, float prevstep);
// interface for collision functions
void collisions_compute_barycentric (float pv[3], float p1[3], float p2[3], float p3[3], float *w1, float *w2, float *w3);
void interpolateOnTriangle(float to[3], float v1[3], float v2[3], float v3[3], double w1, double w2, double w3);
/////////////////////////////////////////////////
#endif

@ -287,7 +287,9 @@ int modifiers_getCageIndex(struct Object *ob,
int *lastPossibleCageIndex_r);
int modifiers_isSoftbodyEnabled(struct Object *ob);
int modifiers_isClothEnabled(struct Object *ob);
int modifiers_isParticleEnabled(struct Object *ob);
struct Object *modifiers_isDeformedByArmature(struct Object *ob);
struct Object *modifiers_isDeformedByLattice(struct Object *ob);
int modifiers_usesArmature(struct Object *ob, struct bArmature *arm);

@ -34,7 +34,7 @@ SET(INC
../python ../render/extern/include ../../../intern/decimation/extern
../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern
../../../intern/iksolver/extern ../blenloader ../quicktime
../../../intern/bmfont
../../../intern/bmfont ../../../extern/bullet2/src
../nodes
${SDL_INC}
${ZLIB_INC}

@ -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 += ' #/intern/opennl/extern'

@ -80,6 +80,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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,810 @@
/* kdop.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_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
*/
DO_INLINE void bvh_exchange(CollisionTree **a, int i, int j)
{
CollisionTree *t=a[i];
a[i]=a[j];
a[j]=t;
}
DO_INLINE 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;
}
}
DO_INLINE 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);
}
}
DO_INLINE 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->current_x)
MEM_freeN(bvh->current_x);
if(bvh->current_xold)
MEM_freeN(bvh->current_xold);
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
DO_INLINE 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
DO_INLINE 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;
}
}
}
}
DO_INLINE void bvh_calc_DOP_hull_static(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
{
MFace *tempMFace = bvh->mfaces;
float *tempBV = bv;
float newminmax;
int i, j, k;
for (j = 0; j < numfaces; j++)
{
tempMFace = bvh->mfaces + (tri [j])->tri_index;
// 3 or 4 vertices per face.
for (k = 0; k < 4; k++)
{
int temp = 0;
// If this is a triangle.
if (k == 3 && !tempMFace->v4)
continue;
// TODO: other name for "temp" this gets all vertices of a face
if (k == 0)
temp = tempMFace->v1;
else if (k == 1)
temp = tempMFace->v2;
else if (k == 2)
temp = tempMFace->v3;
else if (k == 3)
temp = tempMFace->v4;
// for all Axes.
for (i = KDOP_START; i < KDOP_END; i++)
{
newminmax = INPR(bvh->current_xold[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;
}
}
}
}
DO_INLINE void bvh_calc_DOP_hull_moving(BVH * bvh, CollisionTree **tri, int numfaces, float *bv)
{
MFace *tempMFace = bvh->mfaces;
float *tempBV = bv;
float newminmax;
int i, j, k;
for (j = 0; j < numfaces; j++)
{
tempMFace = bvh->mfaces + (tri [j])->tri_index;
// 3 or 4 vertices per face.
for (k = 0; k < 4; k++)
{
int temp = 0;
// If this is a triangle.
if (k == 3 && !tempMFace->v4)
continue;
// TODO: other name for "temp" this gets all vertices of a face
if (k == 0)
temp = tempMFace->v1;
else if (k == 1)
temp = tempMFace->v2;
else if (k == 2)
temp = tempMFace->v3;
else if (k == 3)
temp = tempMFace->v4;
// for all Axes.
for (i = KDOP_START; i < KDOP_END; i++)
{
newminmax = INPR(bvh->current_xold[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(bvh->current_x[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, CollisionTree *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;
}
/* function cannot be directly called - needs alloced bvh */
void bvh_build (BVH *bvh)
{
unsigned int i = 0, j = 0, k = 0;
CollisionTree **face_list=NULL;
CollisionTree *tree=NULL;
LinkNode *nlink = NULL;
tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
// TODO: check succesfull alloc
BLI_linklist_append(&bvh->tree, tree);
nlink = bvh->tree;
if (tree == NULL)
{
printf("bvh_build: Out of memory for nodes.\n");
bvh_free(bvh);
return;
}
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)
{
bvh->root->tri_index = 0; // Why that? --> only one face there
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;
}
// create face boxes
for(i = 0, k = 0; i < bvh->numfaces; i++)
{
LinkNode *tnlink;
tree = (CollisionTree *)MEM_callocN(sizeof(CollisionTree), "CollisionTree");
// TODO: check succesfull alloc
tnlink = BLI_linklist_append_fast(&nlink->next, tree);
face_list[i] = tree;
tree->tri_index = i;
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);
}
}
// bvh_overlap - is it possbile for 2 bv's to collide ?
DO_INLINE 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 ( ClothModifierData * clmd, CollisionModifierData * collmd, CollisionTree * tree1, CollisionTree * tree2, float step, CM_COLLISION_RESPONSE collision_response)
{
int i = 0, ret=0;
/*
// Shouldn't be possible
if(!tree1 || !tree2)
{
printf("Error: no tree there\n");
return 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)
{
// Provide the collision response.
if(collision_response)
collision_response (clmd, collmd, tree1, tree2);
return 1;
}
else
{
// Process the quad tree.
for (i = 0; i < 4; i++)
{
// Only traverse nodes that exist.
if (tree2->nodes[i] && bvh_traverse (clmd, collmd, tree1, tree2->nodes[i], step, collision_response))
ret = 1;
}
}
}
else
{
// Process the quad tree.
for (i = 0; i < 4; i++)
{
// Only traverse nodes that exist.
if (tree1->nodes [i] && bvh_traverse (clmd, collmd, tree1->nodes[i], tree2, step, collision_response))
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
/* you have to update the bvh position before calling this function */
void bvh_update(BVH * bvh, int moving)
{
CollisionTree *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);
}
}
}
}
}

@ -53,6 +53,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"
@ -74,6 +75,7 @@
#include "BKE_main.h"
#include "BKE_anim.h"
#include "BKE_bad_level_calls.h"
#include "BKE_cloth.h"
#include "BKE_curve.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
@ -88,6 +90,7 @@
#include "BKE_object.h"
#include "BKE_mesh.h"
#include "BKE_softbody.h"
#include "BKE_cloth.h"
#include "BKE_material.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
@ -4942,6 +4945,282 @@ static void softbodyModifier_deformVerts(
sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts);
}
/* Cloth */
static void clothModifier_initData(ModifierData *md)
{
ClothModifierData *clmd = (ClothModifierData*) md;
clmd->sim_parms = MEM_callocN(sizeof(SimulationSettings), "cloth sim parms");
clmd->coll_parms = MEM_callocN(sizeof(CollisionSettings), "cloth coll parms");
/* check for alloc failing */
if(!clmd->sim_parms || !clmd->coll_parms)
return;
cloth_init (clmd);
printf("clothModifier_initData\n");
}
static DerivedMesh *clothModifier_applyModifier(ModifierData *md, Object *ob,
DerivedMesh *derivedData, int useRenderParams, int isFinalCalc)
{
ClothModifierData *clmd = (ClothModifierData*) md;
DerivedMesh *result=NULL;
/* check for alloc failing */
if(!clmd->sim_parms || !clmd->coll_parms)
return derivedData;
result = clothModifier_do(clmd, ob, derivedData, useRenderParams, isFinalCalc);
if(result)
{
CDDM_calc_normals(result);
return result;
}
return derivedData;
}
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)
{
CollisionModifierData *coll_clmd = (CollisionModifierData *)modifiers_findByType(ob1, eModifierType_Collision);
if(coll_clmd)
{
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 void clothModifier_copyData(ModifierData *md, ModifierData *target)
{
ClothModifierData *clmd = (ClothModifierData*) md;
ClothModifierData *tclmd = (ClothModifierData*) target;
if(tclmd->sim_parms)
MEM_freeN(tclmd->sim_parms);
if(tclmd->coll_parms)
MEM_freeN(tclmd->coll_parms);
tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms);
tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms);
tclmd->sim_parms->lastcachedframe = 0;
}
static int clothModifier_dependsOnTime(ModifierData *md)
{
return 1;
}
static void clothModifier_freeData(ModifierData *md)
{
ClothModifierData *clmd = (ClothModifierData*) md;
if (clmd)
{
if(G.rt > 0)
printf("clothModifier_freeData\n");
cloth_free_modifier_extern (clmd);
if(clmd->sim_parms)
MEM_freeN(clmd->sim_parms);
if(clmd->coll_parms)
MEM_freeN(clmd->coll_parms);
}
}
/* Collision */
static void collisionModifier_initData(ModifierData *md)
{
CollisionModifierData *collmd = (CollisionModifierData*) md;
collmd->x = NULL;
collmd->xnew = NULL;
collmd->current_x = NULL;
collmd->current_xnew = NULL;
collmd->current_v = NULL;
collmd->time = -1;
collmd->numverts = 0;
collmd->tree = NULL;
}
static void collisionModifier_freeData(ModifierData *md)
{
CollisionModifierData *collmd = (CollisionModifierData*) md;
if (collmd)
{
if(collmd->tree)
bvh_free(collmd->tree);
if(collmd->x)
MEM_freeN(collmd->x);
if(collmd->xnew)
MEM_freeN(collmd->xnew);
if(collmd->current_x)
MEM_freeN(collmd->current_x);
if(collmd->current_xnew)
MEM_freeN(collmd->current_xnew);
if(collmd->current_v)
MEM_freeN(collmd->current_v);
if(collmd->mfaces)
MEM_freeN(collmd->mfaces);
collmd->x = NULL;
collmd->xnew = NULL;
collmd->current_x = NULL;
collmd->current_xnew = NULL;
collmd->current_v = NULL;
collmd->time = -1;
collmd->numverts = 0;
collmd->tree = NULL;
collmd->mfaces = 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 );
// printf("current_time %f, collmd->time %f\n", current_time, collmd->time);
if(current_time > collmd->time)
{
numverts = dm->getNumVerts ( dm );
// check if mesh has changed
if(collmd->x && (numverts != collmd->numverts))
collisionModifier_freeData((ModifierData *)collmd);
if(collmd->time == -1) // first time
{
collmd->x = dm->dupVertArray(dm); // frame start position
for ( i = 0; i < numverts; i++ )
{
// we save global positions
Mat4MulVecfl ( ob->obmat, collmd->x[i].co );
}
collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
collmd->numverts = numverts;
collmd->mfaces = dm->dupFaceArray(dm);
collmd->numfaces = dm->getNumFaces(dm);
// TODO: epsilon
// create bounding box hierarchy
collmd->tree = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->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, collmd->x, numverts*sizeof(MVert));
memcpy(collmd->current_x, collmd->x, numverts*sizeof(MVert));
/* happens on file load (ONLY when i decomment changes in readfile.c */
if(!collmd->tree)
{
collmd->tree = bvh_build_from_mvert(collmd->mfaces, collmd->numfaces, collmd->current_x, numverts, ob->pd->pdef_sbift);
}
else
{
// recalc static bounding boxes
bvh_update_from_mvert(collmd->tree, collmd->current_x, numverts, NULL, 0);
}
}
collmd->time = current_time;
}
else
{
collmd->time = current_time;
}
}
if(dm)
dm->release(dm);
}
/* Boolean */
static void booleanModifier_copyData(ModifierData *md, ModifierData *target)
@ -6765,6 +7044,31 @@ 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->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;
@ -7024,6 +7328,13 @@ int modifiers_isSoftbodyEnabled(Object *ob)
return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
}
int modifiers_isClothEnabled(Object *ob)
{
ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
}
int modifiers_isParticleEnabled(Object *ob)
{
ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem);

@ -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"
@ -113,6 +114,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_cloth.h"
#include "BKE_colortools.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
@ -3004,7 +3006,46 @@ 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= newdataadr(fd, clmd->sim_parms);
clmd->coll_parms= newdataadr(fd, clmd->coll_parms);
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_LOADED;
clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_EDITMODE;
}
else if (md->type==eModifierType_Collision) {
CollisionModifierData *collmd = (CollisionModifierData*) md;
/*
// TODO: CollisionModifier should use pointcache
// + have proper reset events before enabling this
collmd->x = newdataadr(fd, collmd->x);
collmd->xnew = newdataadr(fd, collmd->xnew);
collmd->mfaces = newdataadr(fd, collmd->mfaces);
collmd->current_x = MEM_callocN(sizeof(MVert)*collmd->numverts,"current_x");
collmd->current_xnew = MEM_callocN(sizeof(MVert)*collmd->numverts,"current_xnew");
collmd->current_v = MEM_callocN(sizeof(MVert)*collmd->numverts,"current_v");
*/
collmd->x = NULL;
collmd->xnew = NULL;
collmd->current_x = NULL;
collmd->current_xnew = NULL;
collmd->current_v = NULL;
collmd->time = -1;
collmd->numverts = 0;
collmd->tree = NULL;
collmd->mfaces = NULL;
}
else if (md->type==eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData*) md;
hmd->indexar= newdataadr(fd, hmd->indexar);
@ -3149,7 +3190,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;
/* although not used anymore */
/* still have to be loaded to be compatible with old files */
sb->keys= newdataadr(fd, sb->keys);

@ -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"
@ -155,6 +156,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"
@ -835,6 +837,24 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
writedata(wd, DATA, sizeof(int)*hmd->totindex, hmd->indexar);
}
else if(md->type==eModifierType_Cloth) {
ClothModifierData *clmd = (ClothModifierData*) md;
writestruct(wd, DATA, "SimulationSettings", 1, clmd->sim_parms);
writestruct(wd, DATA, "CollisionSettings", 1, clmd->coll_parms);
}
else if (md->type==eModifierType_Collision) {
CollisionModifierData *collmd = (CollisionModifierData*) md;
/*
// TODO: CollisionModifier should use pointcache
// + have proper reset events before enabling this
writestruct(wd, DATA, "MVert", collmd->numverts, collmd->x);
writestruct(wd, DATA, "MVert", collmd->numverts, collmd->xnew);
writestruct(wd, DATA, "MFace", collmd->numfaces, collmd->mfaces);
*/
}
else if (md->type==eModifierType_MeshDeform) {
MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
int size = mmd->dyngridsize;

@ -291,6 +291,12 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
#define B_BAKEABLE_CHANGE 1470
/* Cloth sim button defines */
#define B_CLOTH_CLEARCACHEALL 1480
#define B_CLOTH_CLEARCACHEFRAME 1481
#define B_CLOTH_CHANGEPREROLL 1482
#define B_CLOTH_RENEW 1483
/* *********************** */
#define B_WORLDBUTS 1600

@ -0,0 +1,655 @@
/**
* $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)
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef DNA_CLOTH_TYPES_H
#define DNA_CLOTH_TYPES_H
#include "DNA_listBase.h"
/**
* 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 vgroup_struct; /* vertex group for scaling structural stiffness */
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? txold */
short vgroup_bend; /* vertex group for scaling bending stiffness */
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; /* UNUSED atm */
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 */
int lastcachedframe;
int editedframe; /* which frame is in buffer */
int autoprotect; /* starting from this frame, cache gets protected */
float max_bend; /* max bending scaling value, min is "bending" */
float max_struct; /* max structural scaling value, min is "structural" */
float max_shear; /* max shear scaling value, UNUSED */
int firstcachedframe;
int pad;
}
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. */
struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */
int flags; /* collision flags defined in BKE_cloth.h */
float avg_spring_len; /* for selfcollision */
}
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; /* unused, only 1 solver here */
unsigned char pad2;
short pad3;
struct BVH *tree; /* collision tree for this cloth object */
struct MFace *mfaces;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
}
Cloth;
#endif
/**
* $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)
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef DNA_CLOTH_TYPES_H
#define DNA_CLOTH_TYPES_H
#include "DNA_listBase.h"
/**
* 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 vgroup_struct; /* vertex group for scaling structural stiffness */
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? txold */
short vgroup_bend; /* vertex group for scaling bending stiffness */
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; /* UNUSED atm */
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 */
int lastcachedframe;
int editedframe; /* which frame is in buffer */
int autoprotect; /* starting from this frame, cache gets protected */
float max_bend; /* max bending scaling value, min is "bending" */
float max_struct; /* max structural scaling value, min is "structural" */
float max_shear; /* max shear scaling value, UNUSED */
int firstcachedframe;
int pad;
}
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. */
struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */
int flags; /* collision flags defined in BKE_cloth.h */
float avg_spring_len; /* for selfcollision */
}
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; /* unused, only 1 solver here */
unsigned char pad2;
short pad3;
struct BVH *tree; /* collision tree for this cloth object */
struct MFace *mfaces;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
}
Cloth;
#endif
/**
* $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)
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef DNA_CLOTH_TYPES_H
#define DNA_CLOTH_TYPES_H
#include "DNA_listBase.h"
/**
* 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 vgroup_struct; /* vertex group for scaling structural stiffness */
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? txold */
short vgroup_bend; /* vertex group for scaling bending stiffness */
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; /* UNUSED atm */
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 */
int lastcachedframe;
int editedframe; /* which frame is in buffer */
int autoprotect; /* starting from this frame, cache gets protected */
float max_bend; /* max bending scaling value, min is "bending" */
float max_struct; /* max structural scaling value, min is "structural" */
float max_shear; /* max shear scaling value, UNUSED */
int firstcachedframe;
int pad;
}
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. */
struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */
int flags; /* collision flags defined in BKE_cloth.h */
float avg_spring_len; /* for selfcollision */
}
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; /* unused, only 1 solver here */
unsigned char pad2;
short pad3;
struct BVH *tree; /* collision tree for this cloth object */
struct MFace *mfaces;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
}
Cloth;
#endif
/**
* $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)
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef DNA_CLOTH_TYPES_H
#define DNA_CLOTH_TYPES_H
#include "DNA_listBase.h"
/**
* 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 vgroup_struct; /* vertex group for scaling structural stiffness */
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? txold */
short vgroup_bend; /* vertex group for scaling bending stiffness */
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; /* UNUSED atm */
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 */
int lastcachedframe;
int editedframe; /* which frame is in buffer */
int autoprotect; /* starting from this frame, cache gets protected */
float max_bend; /* max bending scaling value, min is "bending" */
float max_struct; /* max structural scaling value, min is "structural" */
float max_shear; /* max shear scaling value, UNUSED */
int firstcachedframe;
int pad;
}
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. */
struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */
int flags; /* collision flags defined in BKE_cloth.h */
float avg_spring_len; /* for selfcollision */
}
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; /* unused, only 1 solver here */
unsigned char pad2;
short pad3;
struct BVH *tree; /* collision tree for this cloth object */
struct MFace *mfaces;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
}
Cloth;
#endif
/**
* $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)
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef DNA_CLOTH_TYPES_H
#define DNA_CLOTH_TYPES_H
#include "DNA_listBase.h"
/**
* 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 vgroup_struct; /* vertex group for scaling structural stiffness */
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? txold */
short vgroup_bend; /* vertex group for scaling bending stiffness */
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; /* UNUSED atm */
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 */
int lastcachedframe;
int editedframe; /* which frame is in buffer */
int autoprotect; /* starting from this frame, cache gets protected */
float max_bend; /* max bending scaling value, min is "bending" */
float max_struct; /* max structural scaling value, min is "structural" */
float max_shear; /* max shear scaling value, UNUSED */
int firstcachedframe;
int pad;
}
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. */
struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */
int flags; /* collision flags defined in BKE_cloth.h */
float avg_spring_len; /* for selfcollision */
}
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; /* unused, only 1 solver here */
unsigned char pad2;
short pad3;
struct BVH *tree; /* collision tree for this cloth object */
struct MFace *mfaces;
struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */
}
Cloth;
#endif

@ -32,6 +32,8 @@ typedef enum ModifierType {
eModifierType_ParticleSystem,
eModifierType_ParticleInstance,
eModifierType_Explode,
eModifierType_Cloth,
eModifierType_Collision,
NUM_MODIFIER_TYPES
} ModifierType;
@ -341,6 +343,33 @@ typedef struct SoftbodyModifierData {
ModifierData modifier;
} SoftbodyModifierData;
typedef struct ClothModifierData {
ModifierData modifier;
struct Cloth *clothObject; /* The internal data structure for cloth. */
struct SimulationSettings *sim_parms; /* definition is in DNA_cloth_types.h */
struct CollisionSettings *coll_parms; /* definition is in DNA_cloth_types.h */
} 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 *xold; /* unsued atm, but was discussed during sprint */
struct MVert *current_xnew; /* new position at the actual inter-frame step */
struct MVert *current_x; /* position at the actual inter-frame step */
struct MVert *current_v; /* position at the actual inter-frame step */
struct MFace *mfaces; /* object face data */
unsigned int numverts;
unsigned int numfaces;
int pad;
float time;
struct BVH *tree; /* collision tree for this cloth object */
} CollisionModifierData;
typedef enum {
eBooleanModifierOp_Intersect,
eBooleanModifierOp_Union,

@ -128,6 +128,7 @@ char *includefiles[] = {
"DNA_brush_types.h",
"DNA_customdata_types.h",
"DNA_particle_types.h",
"DNA_cloth_types.h",
// if you add files here, please add them at the end
// of makesdna.c (this file) as well
@ -1148,4 +1149,5 @@ int main(int argc, char ** argv)
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_particle_types.h"
#include "DNA_cloth_types.h"
/* end of list */

@ -51,6 +51,7 @@
#include "DNA_armature_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_curve_types.h"
@ -79,6 +80,7 @@
#include "BKE_blender.h"
#include "BKE_brush.h"
#include "BKE_cloth.h"
#include "BKE_curve.h"
#include "BKE_customdata.h"
#include "BKE_colortools.h"
@ -985,6 +987,8 @@ static uiBlock *modifiers_add_menu(void *ob_v)
/* Only allow adding through appropriate other interfaces */
if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue;
if(ELEM(i, eModifierType_Cloth, eModifierType_Collision)) continue;
if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
(ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
@ -1663,7 +1667,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");
}
@ -1680,8 +1684,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");
but= 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) {
@ -1720,9 +1724,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);
}
@ -1781,6 +1789,10 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
height += 20;
} else if (md->type==eModifierType_Softbody) {
height = 31;
} else if (md->type==eModifierType_Cloth) {
height = 31;
} else if (md->type==eModifierType_Collision) {
height = 19;
} else if (md->type==eModifierType_Boolean) {
height = 48;
} else if (md->type==eModifierType_Array) {
@ -1795,13 +1807,12 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
} else if (md->type==eModifierType_Explode) {
height = 94;
}
/* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, "");
y -= 18;
if (!isVirtual) {
if (!isVirtual && (md->type!=eModifierType_Collision)) {
uiBlockBeginAlign(block);
if (md->type==eModifierType_ParticleSystem) {
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object");
@ -1812,7 +1823,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiButSetFunc(but, modifiers_applyModifier, ob, md);
}
if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem) {
if (md->type!=eModifierType_Softbody && md->type!=eModifierType_ParticleSystem && (md->type!=eModifierType_Cloth)) {
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Copy", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Duplicate the current modifier at the same position in the stack");
uiButSetFunc(but, modifiers_copyModifier, ob, md);
}
@ -3617,6 +3628,10 @@ 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)) {
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
}
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
}
@ -3625,6 +3640,10 @@ 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)) {
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
}
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
allqueue(REDRAWVIEW3D, 0);
}

@ -47,6 +47,7 @@
#include "DNA_scene_types.h"
#include "BKE_action.h"
#include "BKE_cloth.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_library.h"
@ -89,6 +90,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"
@ -2351,6 +2353,78 @@ void do_object_panels(unsigned short event)
if(ob->ipo) ob->ipo->showkey= (ob->ipoflag & OB_DRAWKEY)?1:0;
allqueue(REDRAWVIEW3D, 0);
break;
case B_CLOTH_CLEARCACHEALL:
{
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
if(clmd)
{
// do nothing in editmode
if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE)
break;
/* force freeing because user wants */
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE;
/*user wants to free all, so free whole cloth, this helps to start sim at later frame */
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
CFRA= 1;
update_for_newframe_muted();
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
cloth_clear_cache(ob, clmd, 0);
allqueue(REDRAWBUTSOBJECT, 0);
allqueue(REDRAWVIEW3D, 0);
}
}
break;
case B_CLOTH_CLEARCACHEFRAME:
{
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
if(clmd)
{
// do nothing in editmode
if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE)
break;
/* force freeing because user wants */
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE;
cloth_clear_cache(ob, clmd, MAX2(0.0,G.scene->r.cfra));
// MAX2(1.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)
{
// do nothing in editmode
if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE)
break;
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_RENEW:
{
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
if(clmd)
{
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
allqueue(REDRAWBUTSOBJECT, 0);
allqueue(REDRAWVIEW3D, 0);
}
}
break;
default:
if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
@ -3168,10 +3242,34 @@ static void field_testTexture(char *name, ID **idpp)
}
*idpp = 0;
}
/* 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 );
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWVIEW3D, 0);
}
else
{
BLI_remlink ( &ob->modifiers, md );
modifier_free ( md );
allqueue(REDRAWBUTSEDIT, 0);
}
}
/* Panels for particle interaction settings */
static void object_panel_deflection(Object *ob)
{
uiBlock *block;
uiBut *but;
block= uiNewBlock(&curarea->uiblocks, "object_panel_deflection", UI_EMBOSS, UI_HELV, curarea->win);
if(uiNewPanel(curarea, block, "Deflection", "Physics", 0, 0, 318, 204)==0) return;
@ -3191,7 +3289,9 @@ static void object_panel_deflection(Object *ob)
if(ob->pd && ob->type==OB_MESH) {
PartDeflect *pd= ob->pd;
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",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
uiButSetFunc(but, object_collision__enabletoggle, ob, NULL);
if(pd->deflect) {
uiDefBut(block, LABEL, 0, "Particles", 160,140,75,20, NULL, 0.0, 0, 0, 0, "");
uiDefButBitS(block, TOG, PDEFLE_KILL_PART, B_DIFF, "Kill",235,140,75,20, &pd->flag, 0, 0, 0, 0, "Kill collided particles");
@ -4961,6 +5061,316 @@ errMessage:
#endif // DISABLE_ELBEEM
}
/* Panel for cloth */
static void object_cloth__enabletoggle(void *ob_v, void *arg2)
{
Object *ob = ob_v;
ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
if (!md) {
md = modifier_new(eModifierType_Cloth);
BLI_addhead(&ob->modifiers, md);
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWVIEW3D, 0);
}
else {
Object *ob = ob_v;
ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
if (!md)
return;
BLI_remlink(&ob->modifiers, md);
modifier_free(md);
BIF_undo_push("Del modifier");
ob->softflag |= OB_SB_RESET;
allqueue(REDRAWBUTSEDIT, 0);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWIMAGE, 0);
allqueue(REDRAWOOPS, 0);
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
object_handle_update(ob);
countall();
}
}
static void object_panel_cloth(Object *ob)
{
uiBlock *block;
uiBut *but;
static int val, val2;
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
block= uiNewBlock(&curarea->uiblocks, "object_cloth", UI_EMBOSS, UI_HELV, curarea->win);
if(uiNewPanel(curarea, block, "Cloth ", "Physics", 640, 0, 318, 204)==0) return;
uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
val = (clmd ? 1:0);
but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Cloth", 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)
{
int defCount;
char *clvg1, *clvg2;
char clmvg [] = "Vertex Groups%t|";
val2=0;
/* 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 coefficient (higher = less smaller but more big wrinkles)");
uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,150,150,20, &clmd->sim_parms->stepsPerFrame, 4.0, 100.0, 5, 0, "Quality of the simulation (higher=better=slower)");
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, "Air has normaly some thickness which slows falling things down");
uiDefBut(block, LABEL, 0, "Gravity:", 10,100,60,20, NULL, 0.0, 0, 0, 0, "");
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, B_CLOTH_RENEW, "Pinning of cloth", 10,70,150,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) && (BLI_countlist (&ob->defbase) > 0))
{
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;
}
else
{
if(!clmd->sim_parms->vgroup_mass)
clmd->sim_parms->vgroup_mass = 1;
else if(clmd->sim_parms->vgroup_mass > defCount)
clmd->sim_parms->vgroup_mass = defCount;
}
sprintf (clvg2, "%s%s", clmvg, clvg1);
uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 160,70,150,20, &clmd->sim_parms->vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups");
MEM_freeN (clvg1);
MEM_freeN (clvg2);
}
uiDefButF(block, NUM, B_CLOTH_RENEW, "Pin Stiff:", 10,50,150,20, &clmd->sim_parms->goalspring, 0.0, 500.0, 10, 0, "Pin (vertex target position) spring stiffness");
uiDefBut(block, LABEL, 0, " ", 160,50,150,20, NULL, 0.0, 0, 0, 0, "");
/*
// nobody is changing these ones anyway
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");
*/
}
else if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL)
{
uiDefBut(block, LABEL, 0, " ", 160,70,150,20, NULL, 0.0, 0, 0, 0, "");
uiDefBut(block, LABEL, 0, "No vertex group for pinning available.", 10,50,300,20, NULL, 0.0, 0, 0, 0, "");
}
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);
*/
}
uiBlockEndAlign(block);
uiBlockEndAlign(block);
}
static void object_panel_cloth_II(Object *ob)
{
uiBlock *block;
ClothModifierData *clmd = NULL;
block= uiNewBlock(&curarea->uiblocks, "object_cloth_II", UI_EMBOSS, UI_HELV, curarea->win);
uiNewPanelTabbed("Cloth ", "Physics");
if(uiNewPanel(curarea, block, "Cloth Cache/Collisions", "Physics", 651, 0, 318, 204)==0) return;
uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
if(clmd)
{
uiDefButI(block, NUM, B_CLOTH_RENEW, "First Frame:",10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts");
uiDefButI(block, NUM, B_CLOTH_RENEW, "Last Frame:",160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation stops");
uiDefBut(block, LABEL, 0, "",10,140,300,20, NULL, 0.0, 0, 0, 0, "");
if (!G.relbase_valid)
{
uiDefBut(block, LABEL, 0, "Cache deactivated until file is saved.", 10,120,300,20, NULL, 0.0, 0, 0, 0, "");
uiDefBut(block, LABEL, 0, " ", 10,100,300,40, NULL, 0.0, 0, 0, 0, "");
}
else
{
uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache & Enable Cache Editing", 10,120,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed. This also enabled the cache beeing edited in editmode.");
uiDefBut(block, LABEL, 0, "Clear cache:", 10,100,90,20, NULL, 0.0, 0, 0, 0, "");
uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 100, 100,100,20, NULL, 0.0, 0.0, 10, 0, "Free ALL cloth cache without preroll");
uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 200, 100,110,20, NULL, 0.0, 0.0, 10, 0, "Free cloth cache starting from next frame");
uiDefBut(block, LABEL, 0, " ", 10,80,300,20, NULL, 0.0, 0, 0, 0, "");
}
/*
TODO: implement this again in cloth!
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, "");
*/
uiDefButBitI(block, TOG, CLOTH_COLLSETTINGS_FLAG_ENABLED, B_CLOTH_RENEW, "Enable collisions", 10,60,150,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable collisions with this object");
if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED)
{
uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Min Distance:", 160,60,150,20, &clmd->coll_parms->epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in, can be changed for each frame");
uiDefButS(block, NUM, REDRAWBUTSOBJECT, "Collision Quality:", 10,40,150,20, &clmd->coll_parms->loop_count, 1.0, 100.0, 1.0, 0, "How many collision iterations should be done. (higher = better = slower), can be changed for each frame");
uiDefButF(block, NUM, REDRAWBUTSOBJECT, "Friction:", 160,40,150,20, &clmd->coll_parms->friction, 1.0, 100.0, 1.0, 0, "Friction force if a collision happened");
}
else
uiDefBut(block, LABEL, 0, "",160,60,150,20, NULL, 0.0, 0, 0, 0, "");
}
uiBlockEndAlign(block);
}
static void object_panel_cloth_III(Object *ob)
{
uiBlock *block;
ClothModifierData *clmd = NULL;
block= uiNewBlock(&curarea->uiblocks, "object_cloth_III", UI_EMBOSS, UI_HELV, curarea->win);
uiNewPanelTabbed("Cloth ", "Physics");
if(uiNewPanel(curarea, block, "Cloth Advanced", "Physics", 651, 0, 318, 204)==0) return;
uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
if(clmd)
{
int defCount;
char *clvg1, *clvg2;
char clmvg [] = "Vertex Groups%t|None%x0|";
char clmvg2 [] = "Vertex Groups%t|None%x0|";
uiDefButI(block, NUM, B_DIFF, "Autoprotect Cache From:",10,160,300,20, &clmd->sim_parms->autoprotect, 0.0, MAXFRAME + 1, 1, 0, "Frame on which the simulation gets cache protection enabled automatically (To prevent accidently cleaning it).");
uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_SCALING, B_CLOTH_RENEW, "Enable stiffness scaling",10,130,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "If enabled, stiffness can be scaled along a weight painted vertex group.");
if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING)&& (BLI_countlist (&ob->defbase) > 0))
{
uiDefBut(block, LABEL, 0, "StructStiff VGroup:",10,110,150,20, NULL, 0.0, 0, 0, 0, "");
uiDefBut(block, LABEL, 0, "BendStiff VGroup:",160,110,150,20, NULL, 0.0, 0, 0, 0, "");
defCount = sizeof (clmvg);
clvg1 = get_vertexgroup_menustr (ob);
clvg2 = MEM_callocN (strlen (clvg1) + 1 + defCount, "clothVgST");
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_struct = 0;
}
else
{
if(clmd->sim_parms->vgroup_struct > defCount)
clmd->sim_parms->vgroup_struct = 0;
}
sprintf (clvg2, "%s%s", clmvg, clvg1);
uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 10,90,150,20, &clmd->sim_parms->vgroup_struct, 0, defCount, 0, 0, "Browses available vertex groups");
MEM_freeN (clvg1);
MEM_freeN (clvg2);
defCount = sizeof (clmvg);
clvg1 = get_vertexgroup_menustr (ob);
clvg2 = MEM_callocN (strlen (clvg1) + 1 + defCount, "clothVgBD");
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_bend = 0;
}
else
{
if(clmd->sim_parms->vgroup_bend > defCount)
clmd->sim_parms->vgroup_bend = 0;
}
sprintf (clvg2, "%s%s", clmvg2, clvg1);
uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 160,90,150,20, &clmd->sim_parms->vgroup_bend, 0, defCount, 0, 0, "Browses available vertex groups");
MEM_freeN (clvg1);
MEM_freeN (clvg2);
uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff Max:",10,70,150,20, &clmd->sim_parms->max_struct, clmd->sim_parms->structural, 10000.0, 0.01f, 0, "Maximum structural stiffness value");
uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff Max:",160,70,150,20, &clmd->sim_parms->max_bend, clmd->sim_parms->bending, 10000.0, 0.01f, 0, "Maximum bending stiffness value");
}
else if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING)
{
uiDefBut(block, LABEL, 0, " ", 10,110,300,20, NULL, 0.0, 0, 0, 0, "");
uiDefBut(block, LABEL, 0, "No vertex group for pinning available.", 10,90,300,20, NULL, 0.0, 0, 0, 0, "");
}
}
uiBlockEndAlign(block);
}
void object_panels()
{
Object *ob;
@ -4990,6 +5400,9 @@ void physics_panels()
object_softbodies(ob);
object_softbodies_collision(ob);
object_softbodies_solver(ob);
object_panel_cloth(ob);
object_panel_cloth_II(ob);
object_panel_cloth_III(ob);
object_panel_fluidsim(ob);
}
}

@ -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,8 +73,10 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_multires.h"
#include "BKE_object.h"
#include "BKE_pointcache.h"
#include "BKE_texture.h"
#include "BKE_utildefines.h"
@ -802,7 +805,10 @@ void make_editMesh()
EditFace *efa;
EditEdge *eed;
EditSelection *ese;
int tot, a, eekadoodle= 0;
int tot, a, eekadoodle= 0, cloth_enabled = 0;
ClothModifierData *clmd = NULL;
Cloth *cloth = NULL;
float temp[3];
#ifdef WITH_VERSE
if(me->vnode){
@ -837,10 +843,48 @@ void make_editMesh()
/* make editverts */
CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0);
mvert= me->mvert;
/* lots of checks to be sure if we have nice cloth object */
if(modifiers_isClothEnabled(G.obedit))
{
clmd = (ClothModifierData *) modifiers_findByType(G.obedit, eModifierType_Cloth);
cloth = clmd->clothObject;
/* just to be sure also check vertcount */
/* also check if we have a protected cache */
if(cloth && (tot == cloth->numverts) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT))
{
/* check if we have cache for this frame */
int stack_index = modifiers_indexInObject(G.obedit, (ModifierData *)clmd);
if(BKE_ptcache_id_exist((ID *)G.obedit, G.scene->r.cfra, stack_index))
{
cloth_enabled = 1;
clmd->sim_parms->editedframe = G.scene->r.cfra;
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_EDITMODE;
/* inverse matrix is not uptodate... */
Mat4Invert ( G.obedit->imat, G.obedit->obmat );
if(G.rt > 0)
printf("make_editmesh --> cloth_enabled\n");
}
}
}
evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist");
for(a=0; a<tot; a++, mvert++) {
eve= addvertlist(mvert->co, NULL);
if(cloth_enabled)
{
VECCOPY(temp, cloth->verts[a].x);
Mat4MulVecfl ( G.obedit->imat, temp );
eve= addvertlist(temp, NULL);
/* TODO: what about normals? */
}
else
eve= addvertlist(mvert->co, NULL);
evlist[a]= eve;
// face select sets selection in next loop
@ -969,8 +1013,11 @@ void load_editMesh(void)
EditEdge *eed;
EditSelection *ese;
float *fp, *newkey, *oldkey, nor[3];
int i, a, ototvert, totedge=0;
int i, a, ototvert, totedge=0, cloth_enabled = 0;
ClothModifierData *clmd = NULL;
Cloth *cloth = NULL;
float temp[3], dt = 0.0;
#ifdef WITH_VERSE
if(em->vnode) {
struct VNode *vnode = (VNode*)em->vnode;
@ -1036,9 +1083,60 @@ void load_editMesh(void)
/* the vertices, use ->tmp.l as counter */
eve= em->verts.first;
a= 0;
/* lots of checks to be sure if we have nice cloth object */
if(modifiers_isClothEnabled(G.obedit))
{
clmd = (ClothModifierData *) modifiers_findByType(G.obedit, eModifierType_Cloth);
cloth = clmd->clothObject;
/* just to be sure also check vertcount */
/* also check if we have a protected cache */
if(cloth && (G.totvert == cloth->numverts) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT))
{
/* check if we have cache for this frame */
int stack_index = modifiers_indexInObject(G.obedit, (ModifierData *)clmd);
if(BKE_ptcache_id_exist((ID *)G.obedit, clmd->sim_parms->editedframe, stack_index))
{
cloth_enabled = 1;
/* inverse matrix is not uptodate... */
Mat4Invert ( G.obedit->imat, G.obedit->obmat );
dt = 1.0f / clmd->sim_parms->stepsPerFrame;
}
if(G.rt > 0)
printf("loadmesh --> tot: %d, num: %d\n", G.totvert, cloth->numverts);
}
}
i=0;
while(eve) {
VECCOPY(mvert->co, eve->co);
if(cloth_enabled)
{
if(G.rt > 0)
printf("loadmesh --> cloth_enabled\n");
VECCOPY(temp, cloth->verts[i].x);
VECCOPY(cloth->verts[i].x, eve->co);
Mat4MulVecfl ( G.obedit->obmat, cloth->verts[i].x );
/*
// not physical correct but gives nicer results when commented
VECSUB(temp, cloth->verts[i].x, temp);
VecMulf(temp, 1.0f / dt);
VECADD(cloth->verts[i].v, cloth->verts[i].v, temp);
*/
if(oldverts) {
VECCOPY(mvert->co, oldverts[i].co);
if(G.rt > 0)
printf("loadmesh --> cloth_enabled oldverts\n");
}
i++;
}
else
VECCOPY(mvert->co, eve->co);
mvert->mat_nr= 255; /* what was this for, halos? */
/* vertex normal */
@ -1066,6 +1164,32 @@ void load_editMesh(void)
eve= eve->next;
mvert++;
}
/* burn changes to cache */
if(cloth_enabled)
{
if(G.rt > 0)
printf("loadmesh --> cloth_enabled cloth_write_cache\n");
cloth_write_cache(G.obedit, clmd, clmd->sim_parms->editedframe);
/* in this case we have to get the data for the requested frame */
if(clmd->sim_parms->editedframe != G.scene->r.cfra)
{
cloth_read_cache(G.obedit, clmd, G.scene->r.cfra);
}
clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_EDITMODE;
}
else
{
if(modifiers_isClothEnabled(G.obedit)) {
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(G.obedit, eModifierType_Cloth);
if(G.rt > 0)
printf("loadmesh --> CLOTH_SIMSETTINGS_FLAG_RESET\n");
/* only reset cloth when no cache was used */
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_EDITMODE;
}
}
/* the edges */
a= 0;

@ -101,6 +101,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"
@ -1759,6 +1760,11 @@ void exit_editmode(int flag) /* freedata==0 at render, 1= freedata, 2= do undo b
sbObjectToSoftbody(ob);
}
if(modifiers_isClothEnabled(ob)) {
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
}
if(ob->type==OB_MESH && get_mesh(ob)->mr)
multires_edge_level_update(ob, get_mesh(ob));

@ -77,6 +77,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"
@ -3498,13 +3499,19 @@ 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((ob == OBACT) && modifiers_isClothEnabled(ob)) {
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
if(clmd)
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
}
/* Set autokey if necessary */
if ((!cancelled) && (t->mode != TFM_DUMMY) && (base->flag & SELECT)) {

@ -74,6 +74,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"
@ -467,8 +468,15 @@ void recalcData(TransInfo *t)
/* bah, softbody exception... recalcdata doesnt reset */
for(base= FIRSTBASE; base; base= base->next) {
if(base->object->recalc & OB_RECALC_DATA)
{
if(modifiers_isSoftbodyEnabled(base->object)) {
base->object->softflag |= OB_SB_REDO;
}
else if(modifiers_isClothEnabled(base->object)) {
ClothModifierData *clmd = (ClothModifierData *) modifiers_findByType(base->object, eModifierType_Cloth);
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
}
}
}
}
@ -504,10 +512,16 @@ 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)
{
if(modifiers_isSoftbodyEnabled(ob)) {
ob->softflag |= OB_SB_REDO;
}
else if(modifiers_isClothEnabled(ob)) {
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
}
}
/* proxy exception */

@ -51,6 +51,7 @@
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_brush_types.h"
#include "DNA_cloth_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
@ -64,6 +65,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"
@ -1347,6 +1349,13 @@ 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)) {
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
if(clmd)
clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET;
}
BIF_undo_push("Weight Paint");
allqueue(REDRAWVIEW3D, 0);
}

@ -1,3 +1,4 @@
import os
import os.path
import SCons.Options
@ -56,6 +57,8 @@ def validate_arguments(args, bc):
'VERSE_BUILD_BINARY', 'VERSE_BUILD_DIR', 'VERSE_REGEN_PROTO',
'BF_TWEAK_MODE', 'BF_SPLIT_SRC',
'WITHOUT_BF_INSTALL',
'WITH_BF_OPENMP',
'WITHOUT_BF_INSTALL',
'BF_FANCY',
]
@ -248,6 +251,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', ''),